Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 理解Function.prototype.apply_Javascript_Prototype - Fatal编程技术网

Javascript 理解Function.prototype.apply

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

以下代码取自MDN页面,关于:

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