bob体育官方平台
js功用域使用办法求证

function Test(){ this.name='Test'; var name=2; this.show=function; alert;//显示名字 } } var test=new Test();//通过构造器创建一个对象 test.show();//输出2和'Test' ,说明对象方法访问其属性时必须加this. function Test2(){ this.name='Test2'; this.show=function; alert; } } Test; var test2=new Test2;//输出了Test,Test2,很奇怪啊,name问什么有值了,而且怎么会是'Test',bug? alert; //输出2,test;怎么会有show函数呢,难道是bug //依次输出2,Test;Test,Test2;Test;2,Test // ff和ie6下都是同样的运行结果,看来不是bug,那究竟是为什么呢? // 注意到:对象方法访问其对象的属性时|必须|加以this.. // 整个页面是默认的是|window|对象,那么定义的函数,默认就是window对象的方法。 //直接直接调用函数时,相当于通过window.调用方法,那么方法内部的this自然就是 //window对象,this.name='Test'就是为window对象加了一个属性. // 那么当方法局部作用域内未定义name且调用alert,就相当于调用alert; /*啊,代码混乱了。这看起来像一个很严重的陷阱!!*/

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

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

 代码如下

复制代码

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 {

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(){

返回顶部