【问题标题】:JavaScript: What are .extend and .prototype used for?JavaScript:.extend 和 .prototype 有什么用?
【发布时间】:2011-04-16 10:23:30
【问题描述】:

我对 JavaScript 比较陌生,并且经常在我使用的第三方库中看到 .extend 和 .prototype。我认为这与 Prototype javascript 库有关,但我开始认为情况并非如此。这些是干什么用的?

【问题讨论】:

标签: javascript prototype object-model


【解决方案1】:

Javascript 的继承是基于原型的,因此您可以扩展对象的原型,例如 Date、Math,甚至是您自己的自定义对象。

Date.prototype.lol = function() {
 alert('hi');
};

( new Date ).lol() // alert message

在上面的 sn-p 中,我为 all Date 对象(已经存在的和所有新的)定义了一个方法。

extend 通常是一个高级函数,它复制您要从基类扩展的新子类的原型。

所以你可以这样做:

extend( Fighter, Human )

Fighter 构造函数/对象将继承Human 的原型,因此如果您在Human 上定义livedie 等方法,那么Fighter 也将继承这些方法。

更新说明:

“高级函数”表示 .extend 不是内置的,但通常由 jQuery 或 Prototype 等库提供。

【讨论】:

  • “高级函数”表示.extend 不是内置的,但通常由 jQuery 或 Prototype 等库提供。
  • 补充一点,不建议在JS中扩展原生对象的原型
  • @meder - 您应该在答案中添加 visum 评论。 :)
  • 在现代 Javascript 编程中,习惯上将全局对象和本地对象视为公共浴室的元素;你无法避免进入那里,但你应该尽量减少与表面的接触。这是因为changing the native objects can break other developer's assumptions of these objects, 导致了 javascript 错误,这些错误通常可能需要花费数小时来追踪。这个答案的主要句子似乎歪曲了这种有价值的 javascript 实践。
【解决方案2】:

.extend() 被许多第三方库添加,以便于从其他对象创建对象。有关示例,请参阅 http://api.jquery.com/jQuery.extend/http://www.prototypejs.org/api/object/extend

.prototype 指的是对象的“模板”(如果你想这样称呼它),所以通过向对象的原型添加方法(你在库中看到很多添加到 String、Date、Math、甚至函数)这些方法被添加到该对象的每个新实例中。

【讨论】:

    【解决方案3】:

    extend 方法(例如 jQueryPrototypeJS 中的方法)将所有属性从源对象复制到目标对象。

    现在关于prototype 属性,它是函数对象的成员,是语言核心的一部分。

    任何函数都可以用作constructor,以创建新的对象实例。所有函数都有这个prototype 属性。

    当您在函数对象上使用new 运算符时,将创建一个新对象,并将继承自其构造函数prototype

    例如:

    function Foo () {
    }
    Foo.prototype.bar = true;
    
    var foo = new Foo();
    
    foo.bar; // true
    foo instanceof Foo; // true
    Foo.prototype.isPrototypeOf(foo); // true
    

    【讨论】:

      【解决方案4】:

      Javascript 继承似乎无处不在。堪称“Javascript 语言奇案”。

      这个想法是有一个基类,然后你扩展基类以获得类似继承的功能(不完全,但仍然如此)。

      整个想法是获得原型的真正含义。直到我看到 John Resig 的代码(接近于 jQuery.extend 所做的)编写了一个代码块,他声称 base2 和原型库是灵感的源泉,我才明白这一点。

      这里是代码。

          /* Simple JavaScript Inheritance
           * By John Resig http://ejohn.org/
           * MIT Licensed.
           */  
           // Inspired by base2 and Prototype
          (function(){
        var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
      
        // The base Class implementation (does nothing)
        this.Class = function(){};
      
        // Create a new Class that inherits from this class
        Class.extend = function(prop) {
          var _super = this.prototype;
      
          // Instantiate a base class (but only create the instance,
          // don't run the init constructor)
          initializing = true;
          var prototype = new this();
          initializing = false;
      
          // Copy the properties over onto the new prototype
          for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] = typeof prop[name] == "function" &&
              typeof _super[name] == "function" && fnTest.test(prop[name]) ?
              (function(name, fn){
                return function() {
                  var tmp = this._super;
      
                  // Add a new ._super() method that is the same method
                  // but on the super-class
                  this._super = _super[name];
      
                  // The method only need to be bound temporarily, so we
                  // remove it when we're done executing
                  var ret = fn.apply(this, arguments);        
                  this._super = tmp;
      
                  return ret;
                };
              })(name, prop[name]) :
              prop[name];
          }
      
          // The dummy class constructor
          function Class() {
            // All construction is actually done in the init method
            if ( !initializing && this.init )
              this.init.apply(this, arguments);
          }
      
          // Populate our constructed prototype object
          Class.prototype = prototype;
      
          // Enforce the constructor to be what we expect
          Class.prototype.constructor = Class;
      
          // And make this class extendable
          Class.extend = arguments.callee;
      
          return Class;
        };
      })();
      

      有三个部分在做这项工作。首先,循环遍历属性并将它们添加到实例中。之后,您创建一个构造函数,以便稍后添加到对象中。现在,关键行是:

      // Populate our constructed prototype object
      Class.prototype = prototype;
      
      // Enforce the constructor to be what we expect
      Class.prototype.constructor = Class;
      

      您首先将Class.prototype 指向所需的原型。现在,整个对象都发生了变化,这意味着您需要强制将布局恢复为自己的布局。

      以及用法示例:

      var Car = Class.Extend({
        setColor: function(clr){
          color = clr;
        }
      });
      
      var volvo = Car.Extend({
         getColor: function () {
            return color;
         }
      });
      

      Javascript Inheritance by John Resig 的帖子中了解更多信息。

      【讨论】:

        【解决方案5】:

        第三方库中的一些extend 函数比其他函数更复杂。 Knockout.js 例如包含一个最简单的,它没有 jQuery 所做的一些检查:

        function extend(target, source) {
            if (source) {
                for(var prop in source) {
                    if(source.hasOwnProperty(prop)) {
                        target[prop] = source[prop];
                    }
                }
            }
            return target;
        }
        

        【讨论】:

          【解决方案6】:
          • .extends() 创建一个类,它是另一个类的子类。
            幕后 Child.prototype.__proto__ 将其值设置为 Parent.prototype
            因此方法被继承。
          • .prototype 从一个到另一个继承特性。
          • .__proto__ 是 Prototype 的 getter/setter。

          【讨论】:

          • 不应该是 .extend() 和 not .extends() 吗?
          【解决方案7】:

          这对我来说似乎是最清晰和最简单的例子,这只是附加属性或替换现有的。

          function replaceProperties(copyTo, copyFrom)  {
            for (var property in copyFrom) 
              copyTo[property] =  copyFrom[property]
            return copyTo
          }
          

          【讨论】:

            猜你喜欢
            • 2011-11-22
            • 2019-11-29
            • 1970-01-01
            • 2015-05-15
            • 2013-10-25
            • 2023-03-26
            • 2011-08-03
            • 1970-01-01
            • 2013-06-15
            相关资源
            最近更新 更多