我尝试用这样的代码在JavaScript中模拟'new'运算符:
Function.method('new', function ( ) {
var objPrototype = Object.create(this.prototype);
var instance = this.apply(objPrototype, arguments);
return instance;
});
Run Code Online (Sandbox Code Playgroud)
但是,为了涵盖所有情况,return语句应如下所示:
return (typeof instance === 'object' && instance ) || objPrototype;
Run Code Online (Sandbox Code Playgroud)
现在进行测试:
var SomeClass = function (param1, param2) {
this.param1 = param1;
this.param2 = param2;
};
var test1 = String.new('test1'); //in this case, the "instance" variable is an object
var test2 = SomeClass.new('test1', 'test2'); // in this case, the "instance" variable is undefined
Run Code Online (Sandbox Code Playgroud)
这正是"新"运算符的作用吗?还有什么案子可以解决吗?
从规格:
11.2.2 new操作符# Ⓣ Ⓡ Ⓖ
生产NewExpression:
newNewExpression的计算方法如下:
- 设ref是评估NewExpression的结果.
- 让构造函数为
GetValue(ref).- 如果
Type(构造函数)不是Object,则抛出TypeError异常.- 如果构造函数没有实现[[Construct]]内部方法,则抛出TypeError异常.
- 返回调用上的[[构建]]内部方法的结果的构造,从而提供没有参数(即,自变量列表为空).
生成MemberExpression:
newMemberExpression Arguments 的计算方法如下:
在任何一种情况下,都正确遵循所有步骤:
var objPrototype = Object.create(this.prototype); // 1-4 1-5
var instance = this.apply(objPrototype, arguments); // 5 6
Run Code Online (Sandbox Code Playgroud)
兴趣点是2. 州
的规范[[construct]]:
当使用可能为空的参数列表调用Function对象F的[[Construct]]内部方法时,将执行以下步骤:
- 让obj成为新创建的本机ECMAScript对象.
. . .- 设result是调用F的[[Call]]内部属性的结果,将obj作为this值提供,并将传递给[[Construct]]的参数列表作为args.
- 如果
Type(result)是Object,则返回结果.- 返回obj.
typeof obj返回"object"对null,而null不是一个对象.但是,由于这null是一个虚假值,您的代码也可以按预期工作:
return (typeof instance === 'object' && instance ) || objPrototype;
Run Code Online (Sandbox Code Playgroud)
该new运营商需要一个功能F和arguments:new F(arguments...).它有三个简单的步骤:
创建类的实例.它是一个空属性,其
__proto__属性设置为F.prototype.初始化实例.
使用传递的参数调用函数F,并将其设置为实例.
返回实例
现在我们了解了new运算符的作用,我们可以在Javascript中实现它.
function New (f) {
/*1*/ var n = { '__proto__': f.prototype };
return function () {
/*2*/ f.apply(n, arguments);
/*3*/ return n;
};
}
Run Code Online (Sandbox Code Playgroud)
只是一个小测试,看它是否有效.
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
print: function () { console.log(this.x, this.y); }
};
var p1 = new Point(10, 20);
p1.print(); // 10 20
console.log(p1 instanceof Point); // true
var p2 = New (Point)(10, 20);
p2.print(); // 10 20
console.log(p2 instanceof Point); // true
Run Code Online (Sandbox Code Playgroud)