语法声明和赋值的问题

图片描述

图片描述

为什么示例5显示的值是undefined而不是100?书里的解释太深奥小白表示看不懂。。求各位大神能给个通俗易懂的解释。。感谢。

阅读 2.6k
3 个回答

怎么会使用这样的例子,直接把Object给改了
我们换个名称吧
第1个代码段

(MyObject=function(){}).prototype.value=100;
var myObject=new MyObject();
console.log(myObject.value);//输出100

等价于==>

MyObject=function(){};
MyObject.prototype.value=100;
var myObject=new MyObject();
console.log(myObject.value);//输出100

(MyObject=function(){})是一个赋值表达式,声明了一个全局变量MyObject并一个匿名函数对象赋给它,任何表达式执行完了,都会返回一个值,这里这个值就是MyObject指向的函数对象;接下来执行.prototype.value=100;因为返回的对象是一个函数对象故其默认是有prototype属性-原型对象,为这个原型对象添加了value属性,值为100;
你使用var myObject=new MyObject();创建一个以MyObject为构造函数的实例对象
console.log(myObject.value);按原对象的实例->原型链的顺序查找属性value,在原型链中找到属性value,其值为10。10就被输出

第2个代码段

(function MyObject(){}).prototype.value=100;
var myobj=new MyObject();
console.log(myobj.value);

==>

var temp=(function MyObject(){});
temp.prototype.value=100;
var myobj=new MyObject();
console.log(myobj.value);

==>

var temp=function MyObject(){};
temp.prototype.value=100;
var myobj=new MyObject();
console.log(myobj.value);

(function MyObject(){})也是个表达式调用,将创建一个函数对象,其名字为MyObject,注意这个MyObject名字只在表达式内部有效,外部无法访问到。分析第1段代码我们提到,表达式都有返回值,这个表达式的结果值为一个匿名函数对象temp.prototype.value=100;将会这个匿名函数对象的原型对象添加value属性
var myobj=new MyObject();将抛出执行错误 ReferenceError: MyObject is not defined,究其原因为MyObject在外部没有被定义过

原代码之所以没有报错还有一个全局Object对象存在
为了第2段代码能运行而不报错,我们可以修改如下:

MyObject=function(){};
var temp=(function MyObject(){});
temp.prototype.value=100;
var myobj=new MyObject();
console.log(myobj.value);

代码执行,输出undefined

再修改下:

MyObject=function(){};
MyObject.prototype.value=50;
var temp=(function MyObject(){});
temp.prototype.value=100;
var myobj=new MyObject();
console.log(myobj.value);

输出为50

两个函数都是匿名函数,正常情况下在()外是不能调用的,所以例5是缺省值undefined。
但是例4使用了函数赋值表达式,所以object变量提升了,提升到全局作用域范围。

知识点涉及到了函数声明预编译变量提升

参考地址:
js秘密花园
JS预编译

我个人觉得,这种形式:

(function A() {
    ...
})

实际上就是一个命名的函数表达式,根据规范:

对于命名的函数表达式,它的名称只在函数内看见,在函数外不可见。

所以A这个名称在全局作用域是不存在的。不信你先执行一下上面的代码,然后在执行一下A()试试,是不是提示A没有定义啊?

所以你的例5中,你自定义的Object并没有暴露到全局作用域,当然不会覆盖JS原生的Object。所以重写并没有成功,value自然是undefined。

至于例4,相当于:

(A = function() {
    ...
})

只是一个简单的赋值语句,只不过用括号括了起来。它表示把一个匿名函数复制给一个全局变量A。也就是说,你例4中的Object是全局的,当然也就把原生的Object覆盖了。

所以,本题的关键在于命名的函数表达式

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏