new
作为大家天天使用的操作符,想必大家都不陌生
创建一个对象的通用语法
let obj = new Object();
那么在创建对象的过程中,new 到底做了什么?
MDN
当代码 new Foo(...) 执行时,会发生以下事情:(MDN地址)
- 一个继承自 Foo.prototype 的新对象被创建。
- 使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
- 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
按照这个过程,我们可以大概的模拟一个new的实现
function _new(Super) {
//返回一个function
return (props)=> {
let obj = {}; //创建一个新对象
obj.__proto__ = Super.prototype;//继承父类的属性
let result = Super.apply(obj,props);//调用Super的构造函数
return typeof result === 'object'? result : obj;; //判断Super构造器总返回一个Object
}
}
var a = _new(Super)(['z'])
a;//{name: "z"}
ECMA-262
再次阅读Ecma262
其过程较MDN多了一些判断,如:
new Object ( [ value ] )
当以一个参数 value 或者无参数调用 Object 构造器,采用如下步骤:
-
如果提供了 value, 则
a.如果 Type(value) 是 Object, 则(1)如果 value 是个原生 ECMAScript 对象 , 不创建新对象,简单的返回 value. (2)如果 value 是宿主对象 , 则采取动作和返回依赖实现的结果的方式可以使 依赖于宿主对象的 .
b.如果 Type(value) 是 String, 返回 ToObject(value).
c.如果 Type(value) 是 Boolean, 返回 ToObject(value).
d.如果 Type(value) 是 Number, 返回 ToObject(value). - 断言 : 未提供参数 value 或其类型是 Null 或 Undefined.
- 令 obj为一个新创建的原生 ECMAScript 对象 .
- 设定 obj 的 [[Prototype]] 内部属性为标准内置的 Object 的 prototype 对象.
- 设定 obj 的 [[Class]] 内部属性为 "Object".
- 设定 obj 的 [[Extensible]] 内部属性为 true.
- 设定 obj 的 8.12 指定的所有内部方法
- 返回 obj.
重新来修改下我们的模拟
function _new(Super) {
//返回一个function
return (value) => {
if (value) {
switch (typeof value) {
case 'object':
//这里因为不同的宿主环境也就是不同的引擎会有不同的写法,找了很多博文书籍也没有详解具体的判断逻辑或方法,只好先写伪代码了
if (宿主对象) {
//采取动作和返回依赖实现的结果的方式可以使依赖于宿主对象的
} else {
return value
}
break;
case 'string':
return new String(value);
break;
case 'boolean':
return new Boolean(value);
break;
case 'number':
return new Number(value);
break;
default:
break;
}
}
let obj = {}; //创建一个新对象
obj.__proto__ = Super.prototype; //继承父类的属性
//修改内部属性class 为 “Object”,不过ecma262没有提供任何方法去修改,只提供了一种访问方法 Object.prototype.toString.call("我们的对象")
//修改内部属性Extensible为 true,不过目前没有提供方法去修改,只有一个修改为false Object.preventExtensions("我们的对象");
let result = Super.apply(obj, value); //调用Super的构造函数
return typeof result === 'object' ? result : obj;; //判断Super构造器总返回一个Object
}
}
var a = _new(Super)(['z'])
a; //{name: "z"}
欢迎补充
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。