天天看点

《Javascript高级程序设计》阅读笔记 ----第7章

文章目录

    • 函数执行环境和作用域链
    • 关于this和that的问题
    • 模仿块级作用域
    • 私有变量和公有方法
      • 构造函数模式
      • 静态私有变量
      • 模块模式(单例模式)

函数执行环境和作用域链

要理解JavaScript,必须理解函数执行环境与作用域链(栈)!!

ES5以函数作为执行环境的划分,代码执行从外部到内部,执行环境从外部环境到内部环境依次堆栈,每个函数执行完毕,其执行环境对应的则出栈。

闭包:内部执行环境引用了外部执行环境中的变量,因此外部执行环境的变量不会被销毁。

关于this和that的问题

函数调用时,会搜索谁调用了这个函数。

var name = "The window";
var obj = {
    name: "My obj",
    getName: function(){
        return function(){
            return this.name;
        }
    }
}
alert(obj.getName()()); // "The window"
           

由于调用getName返回的是匿名函数,匿名函数直接运行时,没有人调用它,因此它的this指向window。

假如:

var obj = {
    name: "My obj",
    getName: function(){
        return function(){
            return this.name;
        }
    }
}
obj.test = obj.getName();
obj.test() // “My obj“
           

或者:

var obj = {
    name: "My obj",
    getName: function(){
    	var that = this;
        return function(){
            return that.name;
        }
    }
}
obj.getName()(); // "My obj"
           

模仿块级作用域

由于JS没有块级作用域,而是以函数范围作为作用域划分。所以可以用以下方法模仿块级作用域,使用匿名立即执行函数来创建块级作用域。

(function(){
	//这里是块级作用域
})()
           

由于JS将function关键字当作函数声明的开始,因此不能直接在函数声明后加

()

而是应该用

()

包住函数。

当在全局环境使用该方式时,可以创建自己的私有环境,避免向全局注入过多函数和变量。这在多人协作中很重要。

私有变量和公有方法

构造函数模式

由于函数内部的变量对于外部不可访问,因此可以使用函数来创建私有变量,使用闭包来创建公有方法

function MyObject() {
	var privateVar = 20; // 私有变量
	this.getName = function() { //公有方法
		return privateVar; 
	};
	this.setName = function(value) { //公有方法
		privateVar = value;
	};
}
           

注意,不能写成以下函数:

function MyObject() {
	this.privateVar = 20; // 公有变量
	this.getName = function() { //公有方法
		return this.privateVar; 
	};
	this.setName = function(value) { //公有方法
		this.privateVar = value;
	};
}
           

只要加上this,那么变量就将成为构造函数构造出来的对象的一个可以访问的属性。

这种方法的缺点在于,对于每一个变量都会创建一组相同的新方法。

静态私有变量

创建一个所有实例共享的私有变量和公有方法

//立即执行函数创建私有域
(function(){
	//静态私有变量
	var name = "";
	
	//构造函数
	//Person为全局变量方便外部访问
	Person = function(value) {
		name = value;
	};

	//所有实例的共享方法
	Person.prototype.getName = function(){
		return name;
	};
	Person.prototype.setName = function(){
		name = value;
	};
})();
           

模块模式(单例模式)

例子:一个管理组件的application。

var application = function() {
	//私有,单例变量
	var components = new Array();
	//初始化
	components.push(new BaseComponent());
	
	return {
		//公有接口
		getComponentCount: function() {
			return components.length;
		},
		registerComponent: function(component) {
			if (typeof component == "object") {
				components.push(component);
			}	
		}
		
	}
}
           

继续阅读