资讯专栏INFORMATION COLUMN

使用JavaScript闭包遇到的陷阱(一)

caohaoyu / 2711人阅读

摘要:使用闭包遇到的陷阱一陷阱在类的原型对象中添加特权方法首先定义一个类,该类中有一个私有变量定义个特权方法来访问修改私有变量然后我们对类进行测试到目前为止,类正常工作。

使用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("
page1
"); console.log(page1.getDom());//
page1
var page2=new Page(); page2.setDom("
page2
"); console.log(page2.getDom());//
page2
console.log(page1.getDom());//
page1

到目前为止,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("
page1
"); console.log(page1.getDom());//
page1
var page2=new Page(); page2.setDom("
page2
"); console.log(page2.getDom());//
page2
/* 注意!问题出现了! */ console.log(page1.getDom());//
page2

这时最后一行的console.log(page1.getDom())打印的结果变成了

page2

探究 前提

在使用new操作符调用Page构造函数创建对象的过程:先创建一个Page类的空对象,并将构造函数中的this指向该对象,再执行构造函数。

在函数中定义的变量都保存在该函数执行环境变量对象中。

每个函数都有一个作用域链。函数在定义时,就会生成不完整的作用域链,该作用域的前端是函数定义时所在环境变量对象。函数在执行时,会创建该函数的执行环境,并将该执行环境的活动对象(这里可理解为变量对象)添加到之前创建的作用域链的前端,此时的作用域链是完整的作用域链。

变量访问的过程就是从作用域链家前端沿着作用域链查找变量的过程。

分析

Page类的构造函数使用动态原型的方式来给原型对象添加方法。因此在创建第一个Page实例时,调用Page函数创建执行环境a,这时,会在a中定义setDomgetDom方法并添加到Page类的原型对象中。原型对象中的setDomgetDom方法的作用域链前端都是执行环境a(准确的说是a对应的变量对象)。

创建第一个Page实例时,给Page类的原型对象添加了setDomgetDom方法。之后再创建其他的Page实例时,都不会再修改原型对象中的setDomgetDom方法了。

在创建第二个Page实例时,再次调用Page函数,创建了执行环境b。

在调用Page实例的setDomgetDom方法时,由于都是调用原型对象中的方法。而根据之前说的,原型对象中的setDom方法和getDom方法在访问dom变量的时候,都要沿着作用域链查找,最后找到的是环境a中的变量dom,也就是第一个Page实例的私有变量dom

所以在测试的时候,无论是page1还是page2调用setDomgetDom方法,都是修改或访问page1中的私有变量dom

小结

在类的原型对象中添加的特权方法,不能用来访问或操作类的私有变量,只能用来访问或操作this修饰的特权变量。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79462.html

相关文章

  • JavaScript深入浅出

    摘要:理解的函数基础要搞好深入浅出原型使用原型模型,虽然这经常被当作缺点提及,但是只要善于运用,其实基于原型的继承模型比传统的类继承还要强大。中文指南基本操作指南二继续熟悉的几对方法,包括,,。商业转载请联系作者获得授权,非商业转载请注明出处。 怎样使用 this 因为本人属于伪前端,因此文中只看懂了 8 成左右,希望能够给大家带来帮助....(据说是阿里的前端妹子写的) this 的值到底...

    blair 评论0 收藏0
  • 新鲜出炉8月前端面试题

    摘要:前言最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题主要考察前端技基础是否扎实,是否能够将前端知识体系串联。 前言 最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题: 主要考察前端技基础是否扎实,是否能够将前端知识体系串联。一种是开放式问题: 考察业务积累,是否有自己的思考,思考问题的方式,这类问题没有标准答案。 基础题 题目的答...

    qingshanli1988 评论0 收藏0
  • 前端面试题收集,持续更新中

    摘要:对于所访问的每个元素,函数应该将该元素传递给所提供的回调函数。 HTML 在线阅读Github地址 题目列表 HTML HTML和XHTML的区别 Html的语义化 Doctype的文档类型 cookie、sessionSttorage、localStory区别 HTML全局属性(global attribute)有哪些? 常见的浏览器内核有哪些? 介绍一下你对浏览器内核的理解?...

    kgbook 评论0 收藏0
  • 前端面试题收集,持续更新中

    摘要:对于所访问的每个元素,函数应该将该元素传递给所提供的回调函数。 HTML 在线阅读Github地址 题目列表 HTML HTML和XHTML的区别 Html的语义化 Doctype的文档类型 cookie、sessionSttorage、localStory区别 HTML全局属性(global attribute)有哪些? 常见的浏览器内核有哪些? 介绍一下你对浏览器内核的理解?...

    2json 评论0 收藏0
  • 前端面试题收集,持续更新中

    摘要:对于所访问的每个元素,函数应该将该元素传递给所提供的回调函数。 HTML 在线阅读Github地址 题目列表 HTML HTML和XHTML的区别 Html的语义化 Doctype的文档类型 cookie、sessionSttorage、localStory区别 HTML全局属性(global attribute)有哪些? 常见的浏览器内核有哪些? 介绍一下你对浏览器内核的理解?...

    adam1q84 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<