JavaScript对象创建差异解析及无效实例原因(结合原型机制)
JavaScript对象创建差异与原型深度解析
先把你给出的代码贴出来方便对照:
var a = {x:1}; var b = function(y){this.x = y}; var c = new Object({x:1}); var d = new b(1); var e = b(1); var f = (y) => {return {x:y};}; var g = new f(1); // error var h = f(1); var i = new a();//error
咱们逐个拆解这些变量,结合JS原型链的核心知识,搞明白它们的区别,还有为啥g和i会报错。
1. var a = {x:1};
这是最常用的对象字面量创建方式,属于语法糖,底层和new Object()逻辑类似,但更高效。
a是一个普通对象,它的原型链顶端是Object.prototype(也就是a.__proto__ === Object.prototype为true)。- 注意:
a是对象,不是函数,所以不能用new调用它——这就是后面new a()报错的原因。
2. var b = function(y){this.x = y};
这是一个普通构造函数(本质就是普通函数,只是约定俗成用大写开头,不过这里用了小写b也不影响功能)。
- 作为函数,它的原型是
Function.prototype;同时它自带一个prototype属性,指向一个默认对象(这个对象的constructor属性会指向b自己)。 - 当用
new调用它时,会生成一个绑定了b.prototype的新实例。
3. var c = new Object({x:1});
这是通过Object构造函数创建对象的方式,和a几乎没有本质区别:
c的原型同样是Object.prototype,c.x的值也是1。- 唯一的区别是创建方式:对象字面量是语法糖,写起来更简洁,性能也略优,日常开发里优先用字面量而不是
new Object()。
4. var d = new b(1);
这是正确调用构造函数的方式,生成了b的实例:
- 执行
new b(1)时,JS引擎会先创建一个空对象,把这个对象的__proto__绑定到b.prototype,然后把this指向这个新对象,执行函数体里的this.x = y(也就是把d.x设为1),最后返回这个新对象。 - 所以
d.__proto__ === b.prototype为true,d是b的实例。
5. var e = b(1);
这里直接调用了函数b,没有用new,和构造调用完全是两回事:
- 在非严格模式下,函数里的
this会指向全局对象(浏览器里是window,Node.js里是global),所以执行后全局对象会多一个x属性,值为1;严格模式下this是undefined,这时候会报错Cannot set property 'x' of undefined。 - 因为函数
b没有显式return任何值,所以e的结果是undefined。
6. var f = (y) => {return {x:y};};
这是一个箭头函数,它和普通函数有几个核心差异:
- 没有自己的
this,它的this是继承自外层作用域的; - 没有
prototype属性——这是关键,也是后面new f(1)报错的核心原因; - 不能被当作构造函数使用。
7. var g = new f(1); // error
报错的原因很明确:箭头函数不能作为构造函数。
new操作符的工作流程依赖构造函数的prototype属性:它需要把新创建的对象的__proto__绑定到构造函数的prototype上,但箭头函数根本没有prototype,所以JS引擎会直接抛出TypeError: f is not a constructor的错误。
8. var h = f(1);
直接调用箭头函数f是完全没问题的:
- 箭头函数执行后返回一个对象字面量
{x:1},所以h就是这个对象,它的原型是Object.prototype,和a、c本质上是一样的。
9. var i = new a();//error
报错原因:a是普通对象,不是函数,而new操作符要求后面必须是一个构造函数(也就是函数类型的值)。
- 普通对象没有
prototype属性,也无法完成new操作的绑定原型、绑定this等步骤,所以会抛出TypeError: a is not a constructor的错误。
核心总结
- 只有函数(普通函数、生成器函数等)才能被当作构造函数用
new调用,普通对象不行; - 箭头函数因为没有
prototype属性,不能作为构造函数使用; new调用构造函数会生成绑定了构造函数prototype的新实例,而直接调用函数的this指向全局(非严格模式)或undefined(严格模式);- 对象字面量、
new Object()创建的对象,原型都是Object.prototype;构造函数new出来的实例,原型是构造函数的prototype。
内容的提问来源于stack exchange,提问作者ShAkKiR
相关产品推荐
相关产品推荐

