运用JavaScript闭包碰到的圈套(一)
圈套:在类的原型对象中增加特权要领
起首定义一个Page类,该类中有一个私有变量dom:
function Page(){
var dom;
}
定义2个特权要领来接见、修正私有变量dom:
function Page(){
var dom;
this.setDom=function(newDom){
dom=newDom;
};
this.getDom=function(){
return dom;
}
}
然后我们对Page类举行测试:
var page1=new Page();
page1.setDom("<div>page1<div>");
console.log(page1.getDom());//<div>page1<div>
var page2=new Page();
page2.setDom("<div>page2</div>");
console.log(page2.getDom());//<div>page2</div>
console.log(page1.getDom());//<div>page1<div>
到目前为止,Page类一般事情。
这时刻题目来了:我想每一个Page类的对象都有雷同的特权要领,那就将这两个特权要领增加到Page的原型对象中好了。
function Page(){
var dom;
if(this.__proto__.setDom !== "function"){
this.__proto__.setDom=function(newDom){
dom=newDom;
};
this.__proto__.getDom=function(){
return dom;
};
}
}
对修正后的Page类举行测试:
var page1=new Page();
page1.setDom("<div>page1<div>");
console.log(page1.getDom());//<div>page1<div>
var page2=new Page();
page2.setDom("<div>page2</div>");
console.log(page2.getDom());//<div>page2</div>
/*
注重!题目涌现了!
*/
console.log(page1.getDom());//<div>page2<div>
这时刻末了一行的console.log(page1.getDom())
打印的效果变成了<div>page2<div>
探讨
条件
在运用
new
操纵符挪用Page
组织函数建立对象的历程:先建立一个Page
类的空对象,并将组织函数中的this
指向该对象,再实行组织函数。在函数中定义的变量都保存在该函数实行环境的变量对象中。
每一个函数都有一个作用域链。函数在定义时,就会天生不完全的作用域链,该作用域的前端是函数定义时地点环境的变量对象。函数在实行时,会建立该函数的实行环境,并将该实行环境的运动对象(这里可理解为变量对象)增加到之前建立的作用域链的前端,此时的作用域链是完全的作用域链。
变量接见的历程就是从作用域链家前端沿着作用域链查找变量的历程。
剖析
Page
类的组织函数运用动态原型的体式格局来给原型对象增加要领。因此在建立第一个Page
实例时,挪用Page
函数建立实行环境a,这时刻,会在a中定义setDom
和getDom
要领并增加到Page
类的原型对象中。原型对象中的setDom
和getDom
要领的作用域链前端都是实行环境a(正确的说是a对应的变量对象)。建立第一个
Page
实例时,给Page
类的原型对象增加了setDom
和getDom
要领。以后再建立其他的Page
实例时,都不会再修正原型对象中的setDom
和getDom
要领了。在建立第二个
Page
实例时,再次挪用Page
函数,建立了实行环境b。在挪用
Page
实例的setDom
或getDom
要领时,因为都是挪用原型对象中的要领。而依据之前说的,原型对象中的setDom
要领和getDom
要领在接见dom
变量的时刻,都要沿着作用域链查找,末了找到的是环境a中的变量dom
,也就是第一个Page
实例的私有变量dom
。所以在测试的时刻,无论是
page1
照样page2
挪用setDom
和getDom
要领,都是修正或接见page1
中的私有变量dom
。
小结
在类的原型对象中增加的特权要领,不能用来接见或操纵类的私有变量,只能用来接见或操纵this
润饰的特权变量。