if (!Function.prototype.construct) {
Function.prototype.construct = function(argArray) {
if (! Array.isArray(argArray)) {
throw new TypeError("Argument must be an array");
}
var constr = this;
var nullaryFunc = Function.prototype.bind.apply(
constr, [null].concat(argArray));
return new nullaryFunc();
};
}
运行一下:
复制代码 代码如下:
> Date.construct([2011, 11, 24])
Sat Dec 24 2011 00:00:00 GMT+0100 (CET)
3.3 一个看似更简单的解决方案
你可以手动实现new运算符的操作.例如:
复制代码 代码如下:
var foo = new Foo("abc");
实际上等同于:
复制代码 代码如下:
var foo = Object.create(Foo.prototype);
Foo.call(foo, "abc");
根据这个原理,我们可以写一个简单的库方法:
复制代码 代码如下:
Function.prototype.construct = function(argArray) {
var constr = this;
var inst = Object.create(constr.prototype);
constr.apply(inst, argArray);
return inst;
};
唉!Date作为一个普通函数来调用和作为一个构造函数来调用是一样的:它会忽略掉call()和apply()方法中第一个参数指定的this值,总会生成并返回一个新的实例.
译者注:这里作者理解错了,Date作为普通函数调用和作为构造函数来调用是完全不一样的.不加new的情况下,无论有没有参数,Date()只会返回当前时间的字符串,也就是(new Date()).toString()
复制代码 代码如下:
> Date.construct([2011, 11, 24])
{}
译者注:内置的构造函数中,Array(),Function(),RegExp(),Error()等构造函数在调用时,加new或不加几乎一样.比如Array(10)也是生成一个数组,但Number(),String(),Boolean()就不一样了.不加new它们是类型转换函数,返回的是原始值,加new是构造函数,返回的是对象值.
复制代码 代码如下:
>typeof Number("1")
"number"
>typeof new Number("1")
"object"
正如你所看到的,在操作Date()方法时,我们所写的这个construct()方法并不能如期工作,而且还有一些其他的内置构造函数也表现的和Date一样.不过如果是在操作一个库中自定义的构造函数的时候,这个方法基本可以正常工作(少部分构造函数返回了自己指定的对象值,而不是返回了默认的自动生成的实例this).
译者注:一个构造函数的return语句只要返回的是个对象值,就会覆盖掉默认的this值.比如:
复制代码 代码如下:
function Func1(){
this.value = "this"; return {}
}
function Func2(){
this.value = "this"; return 1}function Func3(){ this.value = "this";}>new Func1() //返回的{}是个对象值,覆盖了默认的this.{}>new Func2() //返回的1是个原始值,所以仍然返回默认的this.{value:"this"}>new Func3() //没有return语句,默认返回了undefined,是个原始值,所以仍然返回默认的this.{value:"this"}>new Func3 //没有参数时,小括号可以省略.{value:"this"}
您可能感兴趣的文章: