函数声明提升的概念(相对于函数表达式)(176):
//不要这样做(函数体内是声明函数)(因为函数相对于表达式是提升的,会出现类似于函数重载的现象,zhezhong 语法是无效的)
if(condition){
function sayHi(){
alert('hi');
}
}else{
function sayHi(){
alert('Yo');
}
}
//可以这样做(函数体内是函数表达式)
var sayHi;
if(condition){
sayHi=function(){
alert('hi!');
}
}else{
sayHi=function(){
alert('Yo!');
}
}
递归(递归函数是在一个函数通过名字调用自身的情况下构成的)(P177)
function factorial(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
闭包(指有权访问另一个函数作用域中的变量的函数,在一个函数中创建另一个函数就是最常见的闭包)(P178)
- 举个例子
function createComparisonFunction(propertyName){
return function(object1,object2){
var value1=object1[propertyName];
var value1=object1[propertyName];
if(value1<value2){
return -1;
}else if(value1>value2){
return 1;
}else{
return 0;
}
}
}
(注:一般在函数执行完毕之后,局部活动对象就会被销毁,内存中仅保存全局作用域,但闭包的情况有所不同)
- 关于this对象
全局函数中,this等于window,匿名函数的执行坏境具有全局性,因此其this对象通常指向window
var name="The Window";
var object={
name:"My Object",
getNameFunc:function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()); //"The Window"
可以修改this的指向
var name="The Window";
var object={
name:"My Object",
getNameFunc:function(){
var that=this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()); //"My Object"
- 内存泄露
function assignHandler(){
var element=document.getElementById("someElement");
element.onclick=function(){
alert(element.id);
};
}
//创建了一个作为element元素时间处理程序的闭包,而这个闭包又创建了一个循环引用,其中匿名函数保存了对assignHandler()的活动对象的引用,因此会导致无法减少element的引用数,所以只要匿名函数存在,element的引用数就至少为1,所以其内存就永远收不回来
//解决方法
function assignHandler(){
var element=document.getElementById("someElement");
var id=element.id;
element.onclick=function(){
alert(id);
};
element=null;
}
模拟块级作用域(P184)
- JS没有块级作用域
//JS没有块级作用域的概念,这意味着在块语句中定义的变量,实际上是包含函数中而非语句中创建的
function outputNumbers(count){
for(var i=0;i<count;i++){
alert(i);//1,2,3,4,5,6,7
}
//没有影响,不会重置变量(多次声明同一个变量,JS会对后续的声明视而不见,但它会执行后续声明中变量的初始化)
var i;
alert(i);//8
}
outputNumbers(8);
- 匿名函数解决没有块级作用域的问题
(function(){
//这里是块级作用域
})();
//上面的代码不但定义了一个匿名函数,而且在定义的同时也调用了它,上面相当于为块级作用域创建了一个私有作用域(块级作用域就是私有作用域)
function outputNumbers(count){
(function(){
for(var i=0;i<count;i++){
alert(i);
}
})();
alert(i); //不会弹出9!
}
outputNumbers(9);
(这种设置块级作用域的技术经常在全局作用域中被用在函数外部,这是为了限制过多的函数和变量成为全局作用域的一部分,因为全局作用于中的变量和函数太多,容易导致命名冲突)
私有变量(P186)
- 特权方法
A:构造函数中定义特权方法
function MyObject(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//特权方法(有权访问私有变量和私有函数的公用方法)
this.publicMethod=function(){
privateVariable++;
return privateFunction();
};
}
B:私有作用域中创建特权方法
(function(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//构造函数
MyObject=function(){
};
//共有(特权)方法(特权方法是在原型上定义的)
Myobject.prototype.publicMethod=function(){
privateVariable++;
return privateFunction();
}
})();
- 模块模式(P189)
//这种模式在需要对单例(里面的对象?)进行某些初始化,同时有需要维护其私有变量时是非常有用的
var singleton=function(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//特权(共有)方法和属性
return{
publiceProperty:true,
publicMethod:function(){
privatevariable++;
return privateFunction(){};
}
};
}();
增强的模块模式
var singleton=function(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//创建对象
var object=new customType();
//添加特权(公共)属性和方法
object.publicProperty=true;
object.publicMethod=function(){
privateVariable++;
return privateFunction();
};
//返回这个对象
return object;
}();