【www.hj8828.com】js作用域使用方法说明

第一个

js作用域用法多样并且一个细节都会产生不同效果,下面我来总结一些js作用域使用方法说明,有需要的朋友可参考。

第二个

一个面试题以它来详细介绍js作用域

第三个

 代码如下

第四个

复制代码

无论我们点击哪个div,反馈的都是第4个div的内容。究其原因,在于每个div的点击事件都与test方法形成了闭包,且每个div的点击事件都共享同一个闭包作用域链。当事件被触发时,变量i所代表的下标已经指向第4个div。可以采用以下几种方式避免由于闭包引起的问题。
使用this转换闭包的作用域链上下文,上例的闭包可以改写为: for (var i = 0;
i < els.length; i++) { var div = els[i]; div.onclick = function() {
alert; return false; } }
当点击div的事件被触发时,查找的作用域已经是“this”所指定的上下文。尽管该事件仍然处于“test”闭包内,但由于不访问或不使用闭包的上下文环境,也就不存在由于闭包作用域内变量被引用所引发的问题。
使点击div的事件与for循环形成闭包,而使得for循环内的变量div不被回收。如:
//for循环内定义闭包方法 for (var i = 0; i < els.length; i++) { var
div = els[i]; a { o.onclick = function() { alert; } } }
//for循环外定义闭包方法 for (var i = 0; i < els.length; i++) { var
div = els[i]; a { o.onclick = function() { alert; } }
//使用匿名方法,其原理与for循环内定义类似 for (var i = 0; i <
els.length; i++) { var div = els[i]; { o.onclick = function() { alert;
} 通过中间方法a或者匿名方法,使for循环体与onclick事情产生闭包。
控制变量的作用域,使点击div的事件所需变量与外层作用域无关。如: for (var
i = 0; i < els.length; i++) { { var div = els[i]; div.onclick =
function() { alert(); }
内部函数自身也可能有内部函数。每次作用域链嵌套,都会增加由创建内部函数对象的执行环境所引发的新活动对象。ECMA262规范要求作用域链是临时性的,但对作用域链的长度却没有加以限制。闭包的潜规则即Function与内部定义的Function之间的相互作用域链上下文环境的关系。如果运用得当,嵌套的内部函数所拥有的潜能将超出了我们的想象力。

function foo(){
 foo.abc = function(){alert(‘Alibaba’)}
 this.abc = function(){alert(‘Alimama’)}
 abc = function(){alert(‘Alipay’)};
 var abc = function(){alert(‘Taobao’)}
}
foo.prototype.abc = function(){alert(‘Alisoft’);}
foo.abc = function(){alert(‘Yahoo’);}
var obj = new foo();
obj.abc();
foo.abc();
abc();

我们就直接针对这输出按顺序进行分析,

 

执行顺序

 代码如下

复制代码

1.foo.prototype.abc = function(){alert(‘Alisoft’);}

//这样之后,我们就可以用obj.abc();不懂prototype原型的,可以看这个prototype原型继承

2.foo.abc = function(){alert(‘Yahoo’);}

//alert yahoo

3.var obj = new foo();

//创建一个foo的实例obj,同时,执行了foo函数,也就是obj.abc() =
function(){alert(‘Alimama’)}

4.foo.abc = function(){alert(‘Alibaba’)}

//foo.abc是foo类的静态方法,在实例化foo后执行了代码片段foo.abc =
function()

//覆盖了原来的foo.abc =
function(){alert(‘Yahoo’);},所以foo.abc()输出alibaba

5.this.abc = function(){alert(‘Alimama’)}

//这句话把function(){alert(‘Alimama’)赋给了obj.abc,所以obj.abc输出alimama

6.abc = function(){alert(‘Alipay’)};    var abc =
function(){alert(‘Taobao’)};

//这两句一起分析,如果没有下一句,那么abc是个全局变量,abc输出alipay

//但是因为下一句var
abc之后,abc的作用域被限制在foo类里,所以外部的abc()会显示未定义.

 

那么,答案就是

alimama

alibaba

undefine

闭包:表示能访问和操作其他本地作用域的变量的表达式(通常是函数)。

作用域

表示变量或函数起作用的区域,指代了它们在什么上下文中执行。Javascript总作用域一共有两种:全局作用域和本地作用域。在Javascript中本地作用域是按照函数来区分的。

 代码如下

复制代码

var global = “11”; //全局作用域

function fun() {

var local = “22”;//本地作用域1

}

function fun2() {

var local2 = “22”;//本地作用域2

for (var i=0;i<100;i++) {

//本地作用域2

}

}

 

不象Java语言那样for循环也是一个作用域,在Javascript中本地作用域是按照函数来区分的。Javascript的作用域概念类似词法作用域。
词法作用域:也叫做静态作用域,变量的作用域是在定义时决定而不是执行时决定。即词法作用域取决于源码,通过静态分析就能确定。

作用域链

与“原型链”类似,Javascript的作用域链也是按有顺序查询的。在访问变量时,先查看本地作用域是否有此变量,如果没有则依次向上一级作用域查找直到全局作用域。如果全局作用域也没有此变量,那么将会在全局作用域中声明这个变量。如下的代码:

 代码如下

复制代码

function f() {

name = “global”;

var local = “local”;

}

f();

console.log(name); //global

console.log(local);//undefine

name变量被声明在全局作用域。

上下文

又可以理解为上下文对象,表示当前代码执行时所处的环境。即是this变量所指代的对象;这么理解比较困难,直接看个例子:

 代码如下

复制代码

function Test() {

console.log(this);

}

Test(); //window

new Test();//Object

在执行Test()时,此时的上下文对象是window,即Javascript的全局对象!在执行new
Test();时新建了一个Object,此时执行Test函数的上下文对象就是Object。如果还不理解,可以看我的如何用Javascript实现面向对象编程一文中有一段代码如下:

 代码如下

复制代码

function newObj(Fun,arguments) {

var o = {};

if (Fun && typeof Fun === “function”) {

o.__proto__ = Fun.prototype;

Fun.apply(o, arguments);

return o;

}

}

 

这主要是new函数操作的模拟,可以看到Fun.apply(o,arguments);这一步,apply的作用是指定执行Fun函数并制定其上下文为o,输入参数为arguments对象。所以new
Test()得到的结果是Object。

闭包

表示能访问和操作其他内部作用域的变量的表达式(通常是函数)。用简单的语言描述就是:能操作其他本地作用域变量的函数就是闭包。还是看代码:

 代码如下

复制代码

function fun() {

var i = 1;

return function() {

i++;

console.log(i);

}

}

var closure = fun();

closure(); //2

closure(); //3

请先按Java语言或其他非闭包语言的逻辑思考。当fun函数执行完毕时,其内部变量i应该会被释放,当closure函数再此执行并调用i时输出错误(因为i未被声明)。但是在Javascript中却打印出了值,这一切都归功于闭包。在执行fun()函数时,闭包就被创建。此时i并没有被释放,closure依然可以被访问到。

另外注意闭包的本质是表达式(通常是函数),所以闭包是在函数生成时定义的。(上面代码的第3行定义闭包)!

闭包的作用

闭包最大的作用就是来阻止外部程序随意访问内部变量,只能通过提供的接口来访问和操作。如下面一个记数器的实现:

 代码如下

复制代码

var counter = (function() {

var i=0;

return {

www.hj8828.com,add:function() {

i++;

return this;

},

get:function() {

return i;

}

}

})();

counter.add().add().add();

console.log(counter.get()); //3

如果不用闭包直接暴露变量,那就会出现如下的情况产生bug:

 代码如下

复制代码

i=0;

function add() {

i++;

}

add();

add();

i+=”1″;

add();

console.log(i);//22

至于为什么产生这么奇怪的结果就要归功与+=和++这两个操作符了。

举一个简单的例子:

 代码如下

复制代码

function test(){

 

alert(this);

 

}

 

var obj=function(){