【问题标题】:javascript prototype confusion [duplicate]javascript原型混淆[重复]
【发布时间】:2011-09-25 16:16:52
【问题描述】:

可能重复:
Javascript - this Vs. prototype

This article 表示原型对象还可以帮助您快速将自定义方法添加到反映在它的所有实例上的对象中。

但是这段代码(不使用原型对象)也为所有实例添加了方法:

function al(){
  this.show = function(){alert('hi!')}

}

var x = new al();
x.show();

var y = new al();
y.show();

原型对象在这里有什么好处?我是不是看错那篇文章了?

【问题讨论】:

    标签: javascript prototype-programming


    【解决方案1】:

    这里的区别是您将方法 show 添加到 al 的实例而不是原型。添加到原型会影响al 的所有实例,而添加到实例只会影响该实例。

    这是一个将show 添加到原型与实例的示例

    function al() {
    
    }
    
    al.prototype.show = function () { alert("hi"); };
    

    这里的关键是现在al 的每个实例都可以访问附加到原型的show 的单个实例。更强大的是通过原型增强现有对象的能力

    var x = new al(); 
    console.log(x.Prop);  // x.Prop === undefined
    al.prototype.Prop = 42;
    console.log(x.Prop);  // x.Prop === 42
    

    【讨论】:

    • 但不是通过原型添加,我可以编辑构造函数定义(例如 this.Prop = 42 inside of function al()) 那么原型对象有什么好处呢?只有 Ben Clayton 说的内存使用情况??
    • @DrStrangeLove:更好的例子是创建一个实例,然后更改原型。您会看到先前创建的对象也具有新属性。因此,通过扩展原型,您可以扩展已经创建的实例。
    • 我明白了。但是向构造函数添加新方法有什么问题?它应该影响所有实例..
    • @DrStrangeLove 你并不总是能够编写构造函数,即使你通过利用原型来编写,你也可以从单独的文件中添加方法,从而保持项目的模块化。
    【解决方案2】:

    主要问题是内存使用。您的第一个代码示例将为您的类的每个实例创建函数“show”的新副本。如果您使用原型方法,则在所有实例之间共享该函数的一个副本。然后使用函数中的“this”运算符来访问正在编辑的实例。

    这对于两个或三个实例可能无关紧要,但如果可能有成百上千个实例,那么每个实例都有单独的函数副本将对您的应用程序的性能产生巨大影响。

    【讨论】:

      【解决方案3】:

      是的,不同之处在于,当您按照自己的方式进行操作时,每个 al 实例都有自己的 show 方法副本。

      如果你把它放在原型上,所有实例共享一个方法的副本,当调用方法时,上下文(即范围)会为你应用。将方法放在原型上会更有效。

      【讨论】:

        【解决方案4】:

        这意味着如果你想在定义al 之后添加一个成员函数或变量——特别是如果al 是由其他人定义的。如果您不了解原型设计,您可以尝试以下方法:

        function al(){
          this.show = function(){alert('hi!')}
        
        }
        
        al.newfunction = function(){alert('hello!')}
        
        var x = new al();
        x.show();
        // THIS WILL FAIL
        x.newfunction();
        

        相反,您需要说:

        al.prototype.newfunction = function(){alert('hello!')}
        
        var x = new al();
        x.show();
        // THIS WILL SUCCEED
        x.newfunction();
        

        【讨论】:

          【解决方案5】:

          您定义的show 方法被标记为al 对象的一部分。 prototype 将允许您扩展现有课程。下面有一个示例,它将向字符串对象添加一个“修剪”函数。将函数添加到代码后,“trim”函数将可用于字符串对象的所有实例

          String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); };
          

          【讨论】:

            【解决方案6】:

            看这个例子。

            <script>
              function al(){
                this.show = function(){alert('hi!')}
              }
            
              var x = new al();
              x.show();
            
              var y = new al();
              y.show();
              y.test = function (){alert('no prototype!')};
              y.test();
              //x.test(); // error 
            
              al.prototype.test2 = function (){alert('prototype!')}; // edit al prototype
              y.test2(); // no error
              x.test2(); // no error
            </script>
            

            【讨论】:

              猜你喜欢
              • 2016-11-19
              • 1970-01-01
              • 2016-05-13
              • 1970-01-01
              • 1970-01-01
              • 2011-04-20
              • 2013-06-14
              • 2013-01-01
              • 2013-04-29
              相关资源
              最近更新 更多