Javascript 理解Function.prototype.apply
以下代码取自MDN页面,关于:Javascript 理解Function.prototype.apply,javascript,prototype,Javascript,Prototype,以下代码取自MDN页面,关于: Function.prototype.construct=函数(aArgs){ var fConstructor=此, fNewConstr=function(){fConstructor.apply(this,aArgs);}; fNewConstr.prototype=fConstructor.prototype; 返回新的fNewConstr(); }; 函数MyConstructor(){ 对于(var nProp=0;nProp
Function.prototype.construct=函数(aArgs){
var fConstructor=此,
fNewConstr=function(){fConstructor.apply(this,aArgs);};
fNewConstr.prototype=fConstructor.prototype;
返回新的fNewConstr();
};
函数MyConstructor(){
对于(var nProp=0;nProp
关于此代码,我有两个问题:
var myInstance=new MyConstructor()
它将调用MyConstructor()
,但如何调用var myInstance=MyConstructor.construct(myArray)代码>调用MyConstructor()
MyConstructor.construct(myArray)
被称为MyConstructor的方法,但该方法被声明为Function.prototype.construct
,而不是MyConstructor.prototype.construct
。Function.prototype.construct
和MyConstructor.prototype.construct
之间有什么区别两个问题的答案都是
这个在construct()
的内部是根据您如何调用它来设置的
如果您编写Function.prototype.construct()
,这将是Function.prototype
,它将中断
编写MyConstructor.construct()
时,这是MyConstructor
,因此代码可以工作
作为补充说明,在支持浏览器时,此代码可以大大简化:
Function.prototype.construct = function (args) {
return new (this.bind.apply(this, [null].concat(args)))();
};
关于你的第一个问题:
MyConstructor
通过一系列间接调用,并传递一个数组作为其参数列表。调用MyConstructor.construct(myArray)
时,此内部construct
将成为MyConstructor
。然后,对它的引用存储为fConstructor
,并创建子构造函数fNewConstr
。该构造函数使用apply
调用MyConstructor
,将myArray
中的元素作为参数传递
作为旁注,这似乎是解释Function.prototype.apply
的一种过于复杂的方式(MDN说这是为了模仿Java,所以可以解释它)
关于第二个问题:
当construct
添加到Function.prototype
时,它在所有函数对象(包括MyConstructor
的实例)上都可用。如果添加到MyConstructor.prototype
会影响MyConstructor
的所有实例,并且当添加到Function.prototype
时会扩展所有函数对象。现在您已经为每个函数创建了一个构造方法,因为您使用Function.prototype
访问了它fConstructor
是一个误导性的变量,因为这个
被分配给它,它实际上是指每个函数
。在作为对象属性的方法内部,此
实际上指的是该方法所属的对象fNewConstr
必须是this.fNewConstr
才能引用每个函数。在这种情况下,它实际上是一个变量,它包含对函数的引用,该函数后来成为函数原型的一部分,使用fNewConstr.prototype=fConstructor.prototype
,然后使用new fNewConstr()
执行。调用newfnewconstr()
时,它使用apply()
传递fConstructor
,或每个函数
一个参数数组。因此,将数组传递给MyConstrutor
TL;医生:
Q1:它是通过嵌套函数调用的,嵌套函数本身由new fNewConstr()
调用调用。它只是允许将参数列表作为数组传递,而不修改函数实际如何使用其参数。
Q2:原型上的任何内容都可以被该构造函数的所有实例访问(并且函数
是JavaScript中所有本机函数的构造函数),但MyConstructor本身不是对象实例,这就是为什么需要在函数.prototype
中定义它的原因
我把我的答案分成两部分,问题1和问题2:
问题1
Function.prototype.construct允许传递数组作为参数列表,而不使用Function.prototype.bind
。它在嵌套函数中调用原始函数,并将传递的参数作为数组,原型设置为原始函数的原型
在给定的代码中,Function.prototype.construct
方法的作用如下
Function.prototype.construct = function (aArgs) {
var fConstructor = this,
第一行允许我们访问正在调用的函数-该范围内This
(规范中的ThisBinding)的值就是我们要调用的函数
fNewConstr = function () { fConstructor.apply(this, aArgs); };
下一行将使用function.prototype.apply
调用原始函数,该函数允许将该函数的参数作为数组传递。将this
作为ThisBinding传递的原因是将this
的属性赋值到被调用函数的ThisBinding,在这种情况下,该函数将是“new”操作符创建的新对象
fNewConstr.prototype = fConstructor.prototype;
这只是使“new”操作符创建的返回对象的原型与调用函数相同,因为“new”操作符是cal
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
new MyConstructor(4, "Hello world!", false); // { property0: 4, property1: 'Hello world!', property2: false }
MyConstructor.construct([4, "Hello world!", false]); // { property0: 4, property1: 'Hello world!', property2: false }
function foo(a, b, c, d, e) { return a + b + c + d + e; }
foo.call(null, 1, 2, 3, 4, 5); // 15
foo.apply(null, [1, 2, 3, 4, 5]); // 15
function foo() { return 1 + 1; }
Function.prototype.bar = function ()
{ var result = this();
if (typeof result === 'number' && isFinite(result)) return result + 0.5;
return NaN;
};
foo.bar(); // 2.5
function MyConstructor(num) { this.x = 1 + num; }
MyConstructor.prototype.bar = function () { return 2 + 2; };
MyConstructor.bar(); // TypeError: MyConstructor.bar is not a function
MyConstructor.x; // undefined
var foo = new MyConstructor(4);
foo.x; // 5
foo.bar(); // 4
function MyConstructor(num) { this.x = 1 + num; }
MyConstructor.prototype.bar = function () { return 2 + 2; };
var foo1 = new MyConstructor(6);
foo1.bar(); // 4
MyConstructor.prototype.bar = function () { return 3 + 3; };
var foo2 = new MyConstructor(9);
foo2.bar(); // 6
foo1.bar(); // 6
var foo1 = new MyConstructor(6);
foo1.bar(); // 4
MyConstructor.prototype = { bar: function () { return 3 + 3; } };
var foo2 = new MyConstructor(9);
foo2.bar(); // 6
foo1.bar(); // 4?!
MyConstructor.bar2 = function () { return 42; }; // the answer to everything?
MyConstructor.y = 3.141592653589793238462643383279502881197169399; // I only can remember that much
MyConstructor.bar2(); // 42, as you'd expect
var foo = new MyConstructor(99);
foo.bar2(); // TypeError: foo.bar2 is not defined
foo.y; // undefined