JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染
2023-06-13 09:14:25 时间
如代码块
复制代码代码如下:
if(true){
inti=100;
}
print(i);//错误,变量i没有声明
如上面例子所示,代码块外的函数是无法访问i变量的。
但在javaScript里,情况则完全不同。
if(true){
vari=100;
}
alert(i);//弹出框并显示100
很多现代语言都推荐尽可能迟地声明变量,但在Javascript里这是一个最糟糕的建议。由于缺少块级作用域,最好在函数体的顶部声明函数中可能用到的所有变量。
闭包特性:
虽然缺少块级作用域,但是函数的作用域还是存在的。
这种作用域有一个好处,就是内部函数可以访问定义它们的外部函数的参数和变量(除了this和argument)。
利用这种特性,则可以这样来设计代码。
varbankAccount=function(){
varvalue=0;
return{
deposit:function(inc){
value+=inc;
},
getValue:function(){
returnvalue;
}
}
}
varmyAccount=bankAccount();//新开一个银行账户
myAccount.deposit(1000);//存1000块进去
alert(myAccount.getValue());//shouldalert(1000);
value由于在bankAccount这个function里,外部无法对它进行直接操作,必须通过bankAccountfunction给他返回的对象来进行操作,通过这样来实现C#和java里的private的字段。
减缓全局变量污染全局空间:利用函数的作用域,我们在写js库的时候可以减少跟其他库冲突。
(function(){
varhello="HelloWorld.";
})();
alert(hello);//error:hellonoexist.
这里的语法很有点诡异,主要思想是定义一个匿名方法,并且马上执行。由于function开头这个litertal会被解释作为函数定义,这里加上了一对括号包住它,然后再用一对括号表示调用此函数。外部的alert访问不到在函数内部定义的hello。
陷阱一:var的陷阱
“减缓全局变量污染全局空间”的例子改成
(function(){
hello="HelloWorld.";//removevar
})();
alert(hello);//alert("HelloWorld.");
当变量hello没有用var显式声明时,hello成为了一个全局变量!!
虽然利用这个特性,咱们可以提供一个对外接口,但不建议这样做。
(function(){
varhello="HelloWorld.";
sayHello=function(){//不建议采用这种方式来提供接口,看起来很不明显。
alert(hello);
}
})();
sayHello();
可以改进为
(function(window){
varhello="HelloWorld.";
window.$={
sayHello:function(){
alert(hello);
}
};
})(window);
$.sayHello();//看起来像jQuery那么酷
或
varobj=(function(){
varhello="HelloWorld.";
return{
sayHello:function(){
alert(hello);
}
};
})();
obj.sayHello();
陷阱二:闭包的陷阱
(function(){//函数a
vararr=[];
vari=0;
varj;
for(;i<3;i++){
arr.push(function(){//函数b
alert(i*10);
});
}
for(jinarr){
arr[j]();
}
})();
原以为函数数组arr里各个函数执行后,会弹出0,10,20,但是结果不是如此。结果是弹出30,30,30。
函数b访问的不是当时的i的值,而是直接访问变量i(用于都是取i最新的值)。
原因是函数b是函数a的内部函数,变量i对函数b是可见的,函数b每次都从i处获取最新的值。
这次改成:
(function(){//函数a
vararr=[];
vari=0;
varj;
for(;i<3;i++){
arr.push((function(anotherI){//函数m
returnfunction(){//函数b
alert(anotherI*10);
}
})(i));//此处为(functionb(anotherI){})(i)
}
for(jinarr){
arr[j]();
}
})();
这次执行后,终于弹出0,10,20。这是为什么呢。
函数b访问的是anotherI(当时的i的值),而不是直接访问变量i。
每次在arr.push前,都会定义一个新匿名的函数m。本例中定义了3个匿名函数m0,m1,m2,每当被调用后,他们的anotherI都得到当前i的值。每个m函数执行后都返回一个b函数。b0在m0里,b1在m1里,b2在m2里。b0只能访问m0的anotherI(为0),而b0访问不了m1的anotherI,因为m0和m1为不同的函数。
相关文章
- JavaScript 引擎性能比较之一SpiderMonkey[通俗易懂]
- JavaScript刷LeetCode拿offer-js版字典
- 说说JavaScript闭包
- 用javascript分类刷leetcode6.深度优先&广度优先(图文视频讲解)_2023-03-15
- WebStorm 2023 for Mac 永久激活版: 最强大的JavaScript集成开发环境
- javascript 正则表达式详解编程语言
- AMP与Oracle结合提升数据库性能($amp oracle)
- Javascript常用运算符(Operators)-javascript基础教程
- 国外的为初学者写的JavaScript教程
- Javascript&DHTMLDOM基础和基本API
- Javascript阻止javascript事件冒泡,获取控件ID值
- JavaScript异步调用框架(Part1-问题&场景)
- JavaScript常用函数库详解
- Javascript中的&&和||使用小结
- JavaScript设计模式富有表现力的Javascript(一)
- Javascript异步加载详解(浏览器在javascript的加载方式)
- JavaScript面向对象(极简主义法minimalistapproach)
- JavaScript布尔操作符解析&&||!
- Javascript事件实例详解
- javascript实现日期格式转换
- JavaScript中的逻辑判断符&&、||与!介绍
- 原生javascript实现图片弹窗交互效果
- 浅谈Javascript数组与字典
- 如何用JavaScript定义一个类