资讯专栏INFORMATION COLUMN

JavaScript中的函数

coolpail / 1625人阅读

摘要:然后最后一步就是从父作用域链中将该特殊对象删除,整个过程的伪代码如下注意这里,该属性不能删除,只读。

起因是我在逛sf的时候看到了一个人的提问:

为什么将函数c赋值给变量b,在函数体里面,给c赋值,为什么会失败?也就是这代码执行时为什么c打印出来的不是3

var  b = function c () {
    a=1, b=2, c=3;
    console.log(a);
    console.log(b);
    console.log(c);
}
b();

把上面这段代码在控制台中运行一下,得出的结果是:

1
2 
f c(){ ... }

看到其他的回答中有一个说c被声明成了全局变量,我当时是比较怀疑的,因为这种具名函数表达式是可以用函数名调用自身的,c会是函数本身的引用,所以我把console.log(c)改成了console.log(window.c)

var b = function c() {
    a=1, b=2, c=3;
    console.log(a);
    console.log(b);
    console.log(window.c);
}
b();

再执行,输出的结果是: 1 2 undefined,很明显,c并没有声明到全局,所以说c=3这个语句只是静默失败了。在非严格模式下,JavaScript代码的很多行为都会静默失败,但在严格模式下就会暴露问题所在,然后我给这个函数加上"use strict"再运行一下:

var b = function c() {
    "use strict";
    var a=1, b=2;
    c=3;
    console.log(a);
    console.log(b);
    console.log(window.c);
}
b();

果然报错:Uncaught TypeError: Assignment to constant variable.,说明这个c是不可变的,至于为什么不可变,就属于JavaScript函数本身的特点了。然后我在网上搜索了一些资料,在ECMA-262-3 in detail. Chapter 5. Functions.找到了一点相关内容,文中提到了具名函数表达式(NFE)的一些特点,比如如下的例子:

(function foo(bar) {
  
  if (bar) {
    return;
  }
  
  foo(true); // "foo" name is available
  
})();
  
// but from the outside, correctly, is not
  
foo(); // "foo" is not defined

其中一个特点是foo这个名字在函数内部可用,这个特点由NFE的工作方式决定:
当解释器在执行遇到具名函数表达式时,在创建函数表达式之前,它会创建一个特殊的辅助对象,并且加载当前的作用域链上。然后创建函数表达式本身,在该阶段函数获得[[Scope]]属性,即创建函数的上下文作用域链,然后函数表达式的name会作为唯一(unique)的属性添加到特殊对象上,属性的值就是函数表达式的引用。然后最后一步就是从父作用域链中将该特殊对象删除,整个过程的伪代码如下:

specialObject = {};
  
Scope = specialObject + Scope;
  
foo = new FunctionExpression;
foo.[[Scope]] = Scope;
specialObject.foo = foo; // {DontDelete}, {ReadOnly} 注意这里,该属性不能删除,只读。
  
delete Scope[0]; // remove specialObject from the front of scope chain

对NFE工作原理理解过后,就很容易理解NFE的特性和文章开头的问题了。

结尾广告部分

网易考拉招聘高级前端开发工程师,坐标杭州滨江网易大厦,有兴趣的请戳我了解&投递简历

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

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

相关文章

  • JavaScript深入浅出

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

    blair 评论0 收藏0
  • JS程序

    摘要:设计模式是以面向对象编程为基础的,的面向对象编程和传统的的面向对象编程有些差别,这让我一开始接触的时候感到十分痛苦,但是这只能靠自己慢慢积累慢慢思考。想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。 JavaScript 中的构造函数 学习总结。知识只有分享才有存在的意义。 是时候替换你的 for 循环大法了~ 《小分享》JavaScript中数组的那些迭代方法~ ...

    melody_lql 评论0 收藏0
  • 学习React之前你需要知道的的JavaScript基础知识

    摘要:和类在开始时遇到类组件,只是需要有关类的基础。毕竟,中的条件呈现仅再次显示大多数是而不是特定的任何内容。 在我的研讨会期间,更多的材料是关于JavaScript而不是React。其中大部分归结为JavaScript ES6以及功能和语法,但也包括三元运算符,语言中的简写版本,此对象,JavaScript内置函数(map,reduce,filter)或更常识性的概念,如:可组合性,可重用...

    bitkylin 评论0 收藏0
  • JavaScript中的面向对象(object-oriented)编程

    摘要:对象在中,除了数字字符串布尔值这几个简单类型外,其他的都是对象。那么在函数对象中,这两个属性的有什么区别呢表示该函数对象的原型表示使用来执行该函数时这种函数一般成为构造函数,后面会讲解,新创建的对象的原型。这时的函数通常称为构造函数。。 本文原发于我的个人博客,经多次修改后发到sf上。本文仍在不断修改中,最新版请访问个人博客。 最近工作一直在用nodejs做开发,有了nodejs,...

    JerryZou 评论0 收藏0
  • 深入理解JavaScript,这一篇就够了

    摘要:也就是说,所有的函数和构造函数都是由生成,包括本身。如果只考虑构造函数和及其关联的原型对象,在不解决悬念的情况下,图形是这样的可以看到,每一个构造函数和它关联的原型对象构成一个环,而且每一个构造函数的属性无所指。 前言  JavaScript 是我接触到的第二门编程语言,第一门是 C 语言。然后才是 C++、Java 还有其它一些什么。所以我对 JavaScript 是非常有感情的,毕...

    villainhr 评论0 收藏0

发表评论

0条评论

coolpail

|高级讲师

TA的文章

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