一:函数表达式和函数声明
1:函数声明和函数表达式的区别
①函数声明不需要分号结尾
②函数声明有函数提升的特点
③函数声明后面不能跟圆括号直接调用,因为javascript将function关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号!
2:匿名函数的作用
①作为值使用
function sum(num1,num2){
return function(num1,num2){
return num1+num2;
}
}
3:闭包
概念:是指有权访问另一个函数作用域中的变量的函数。(通过在一个函数内部创建另一个函数得到闭包)
①当一个函数被调用时,会创建一个执行环境和相应的作用域链,使用arguments和其他命名参数的值来初始化函数的活动对象。外部函数的活动对象在作用域链中处于次位。
②
function compare(value1,value2){
if(value<value2){
return -1;
} else if(value1>value2){
return 1;
} else {
return 0;
}
} //调用compare()时,会创建一个包含arguments,value1和value2的活动对象。全局执行环境的变量对象(包括result和compare)在compare()执行环境的作用域链中处于第二位。
③后台的每个执行环境中都有一个变量对象。全局对象一直存在,像compare()函数这样的局部环境的变量对象,则只在函数执行的过程中存在。
作用域链本质上事一个指向变量对象的指针列表,它只引用但不实际包含变量对象。
④而闭包———在create()函数内部定义的匿名函数的作用域链中,实际上将会包含外部函数create()的活动对象。
var create1 = create("name");
var result = carete1({name:"Wang"},{name:"Lee"}); //函数create中有匿名函数
在函数create执行完之后,因为匿名函数的作用域链依旧在引用这个活动对象,所以它的活动对象不会被销毁。(但create()执行完后create()的作用域链被销毁)
通过
create1 = null;
销毁匿名函数的作用域链。
二.关于this对象(易出错)
1:匿名函数的执行环境具有全局性,因此this对象通常指向window。但是由于闭包的写法因此并不明显
var name = "global"; var object = {
name : "part",
getName : function(){
return function(){
return this.name;
}
}
}; alert(object.getName()());
//global
2:每个函数在被调用的时候会自动取得两个特殊变量:this和arguements。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不会直接访问外部函数中的这两个变量。
需要把this保存在变量中才能让闭包访问到。
var name = "The Window"; var object = {
name : "My object",
getName : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getName()());
//My object
三.私有作用域
用作私有作用域(块级作用域)的语法如下:
(function(){ //这里是块级作用域 })();
这种技术经常在全局作用域中用在函数外部,从而限制向全局作用域中添加过多的变量和函数。比如
(function(){ var now = new Date();
if(now.getMonth()==0&&now.getDate()==1){
alert("Happy");
}
})(); //这段代码在1月1日的时候显示祝贺新年的消息
四.私有变量和特权方法
①私有变量:在函数内部定义的变量
②特权方法:有权访问私有变量和私有函数的公有方法称为特权方法(利用闭包实现)
function PP(name) {
this.getName : function(){
return name;
}
} var ppp = new PP("hehe");
alert(ppp.getName());
③通过getName()方法访问私有变量name,但是这种写法有个缺点:必需使用构造函数模式来完成。——其他创建私有变量和特权方法的模式见书,暂时不深入