资讯专栏INFORMATION COLUMN

JS中的new和作用域链

calx / 1360人阅读

摘要:同时构造函数内部的被指定为。这时的作用域链是由的活动对象和全局对象组成的。在被调用时,它自身的活动对象被创建,然后添加到了中存储着的作用域链的最前方。当函数执行完毕时活动对象会被从该作用域链上删除。参考自运算符作用域原理译函数的作用域链

new的运行机制

当代码new Animal("cat")执行时:

var obj=Object.create(Animal.prototype);

传入cat参数,构造函数Animal执行。同时构造函数内部的this被指定为obj。

如果构造函数返回了一个“对象”,那么这个对象就是new出来的结果。如果构造函数没有返回对象(即返回一个非对象值,例如数值,或者无返回值),那么new出来的结果为obj对象。一般情况下构造函数不返回值,除非你想要覆盖正常创建的对象(即obj)。

例如:

function A(name){
  this.name=name;
  return 3;
}
var new1=new A("aa");
new1;//A {name: "aa"}

function B(name){
  this.name=name;
  return {};
}
var new2=new B("aa");
new2;//new2为一个空对象。
作用域链

JS权威指南中有一句很精辟的描述: “JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。”简单来说,就是函数被调用时,它是运行在当时定义该函数时的环境中的。

定义函数

定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时所在的“环境”,并为a添加scope属性,a.scope=a的作用域链。如果a定义在全局环境,那么scope chain中只有window对象。

调用函数

函数被调用时,会创建一个活动对象(call object)(也就是一个对象), 然后把所有函数a的局部变量和函数定义添加为该活动对象的属性, 并将该活动对象添加到a的作用域链的最顶端,此时a的作用域链包含2个对象:a的活动对象和window对象。

案例解析

为什么调用func1(10)和func2(10)时,引用到了两个不同的i?

function outerFn(i, j) {
    var x = i + j;
    return function innerFn(x) {
        return i + x;
    }
}
var func1 = outerFn(5, 6);
var func2 = outerFn(10, 20);
alert(func1(10)); //返回15
alert(func2(10)); //返回20

调用outerFn (5, 6)的时候定义了一个新的函数对象innerFn,然后该函数对象成为了outerFn函数的活动对象的一个属性。这时innerFn的作用域链是由outerFn的活动对象和全局对象组成的.。这个作用域链存储在了innerFn函数的内部属性[[scope]]中,然后返回了该函数,变量func1就指向了这个innerFn函数。

在func1被调用时,它自身的活动对象被创建,然后添加到了[[scope]]中存储着的作用域链的最前方。这时的作用域链才是func1函数执行时用到的作用域链。从这个作用域链中,可以看到变量‘i’的值实际上就是在执行outerFn(5,6)时产生的活动对象的属性i的值。下图显示了整个流程。

下图是func2执行时的情况。因为在定义func1和func2时,函数outerFn中产生过两个不同的活动对象,所以才导致调用func1(10)和func2(10)时,引用到了两个不同的i。

一个活动对象在函数执行的时候创建,同时被添加到该函数的作用域链的最前端。当函数执行完毕时,活动对象会被从该作用域链上删除。但是该活动对象是否会被垃圾回收器销毁,还要看其他地方是否还有使用到该活动对象。

参考自:
new运算符
Javascript作用域原理
[译]JavaScript:函数的作用域链

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

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

相关文章

  • 夯实JS系列--变量、作用内存问题

    摘要:作用域链的用途,是保证对执行环境有权访问的变量和函数的有序访问。全局执行环境始终是作用域链的最后一个对象。延长作用域链虽然执行环境的类型只有两种。 最近在忙于写一个react+node的全栈博客demo,没有时间更新文章。但是还是觉得这样一忙起来不更新是不应该的。正好在空闲上下班地铁上都会再去细读js原生知识。所以打算整理、总结、系统性的分享给大家。 基本类型和引用类型 在ECMASc...

    sihai 评论0 收藏0
  • Js 中的闭包this

    摘要:自由变量指的是不在函数内部声明的变量。作用域链就是在所有内部环境中查找变量的链式表。闭包的形式闭包的过程写的不是很严谨。 要弄懂这个问题首先要搞清楚一个概念, 执行上下文。 执行上下文 执行上下文是什么? 可以简单理解执行上下文是js代码执行的环境,当js执行一段可执行代码时,会创建对应的执行上下文。他的组成如下: executionContextObj = { this: 对...

    AlphaWatch 评论0 收藏0
  • JS基础知识:变量对象、作用域链闭包

    摘要:前言这段时间一直在消化作用域链和闭包的相关知识。而作用域链则是这套规则这套规则的具体运行。是变量对象的缩写那这样放有什么好处呢我们知道作用域链保证了当前执行环境对符合访问权限的变量和函数的有序访问。 前言:这段时间一直在消化作用域链和闭包的相关知识。之前看《JS高程》和一些技术博客,对于这些概念的论述多多少少不太清楚或者不太完整,包括一些大神的技术文章。这也给我的学习上造成了一些困惑,...

    Keven 评论0 收藏0
  • 温故js系列(14)-闭包&垃圾回收&内存泄露&闭包应用&作用域链&

    摘要:该对象包含了函数的所有局部变量命名参数参数集合以及,然后此对象会被推入作用域链的前端。如果整个作用域链上都无法找到,则返回。此时的作用域链包含了两个对象的活动对象和对象。 前端学习:教程&开发模块化/规范化/工程化/优化&工具/调试&值得关注的博客/Git&面试-前端资源汇总 欢迎提issues斧正:闭包 JavaScript-闭包 闭包(closure)是一个让人又爱又恨的somet...

    Amio 评论0 收藏0
  • js知识梳理6:关于函数的要点梳理(2)(作用域链闭包)

    摘要:在此例中,在匿名函数被返回后,它的作用域链初始化为包含函数的活动对象和全局变量对象。函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象,结果就是只是的执行环境的作用域链会被销毁,其活动对象会留在内存中。 写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,...

    aristark 评论0 收藏0

发表评论

0条评论

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