【问题标题】:Is it ok to define a prototype function on Object in Javascript? [duplicate]可以在 Javascript 中的 Object 上定义原型函数吗? [复制]
【发布时间】:2013-03-15 06:27:46
【问题描述】:
Object.prototype.doSomething = function(p) {
    this.innerHTML = "<em>bar</em>";
    this.style.color = "#f00";
    alert(p);
};

document.getElementById("foo").doSomething("Hello World");

&lt;div id="foo"&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/div&gt;

上面的代码运行良好。

但我记得我在某个地方看到过这个:Do not mess with native Object. 嗯,类似的。

那么在Object上定义原型函数可以吗?有什么理由我不应该这样做吗?

【问题讨论】:

  • 这是给别人使用的图书馆吗?还是为您自己的应用程序代码?
  • 我正在编写一个其他人可能也在使用的小型库。正如下面建议的答案,我认为无论代码是为谁编写的,我都不应该这样做。

标签: javascript function object prototype


【解决方案1】:

添加到Object.prototype 的唯一安全方法是使用ES5 方法Object.defineProperty 创建一个不可枚举 属性:

Object.defineProperty(Object.prototype, 'doSomething', {
    value: function(p) { ... },
    enumerable: false,  // actually the default
});

这样可以确保在您执行for (key in object) 时不会出现新属性。

请注意,此函数无法可靠地填充,因为不可枚举的属性在以前版本的 ECMAScript / JavaScript 中不存在。

无论如何,如果您的方法仅适用于 HTML 页面元素,您最好将其添加到 Element.prototype 而不是 Object.prototype,尽管如果您这样做,旧 (IE) 浏览器可能会抱怨。

【讨论】:

  • 现在hasOwnProperty 不是最佳实践吗?
  • @RoatinMarth 不,恕我直言hasOwnProperty最佳做法。在 ES5 浏览器中,它应该是不必要的。任何不干净地与Object.prototype 混淆的代码都应该被淘汰。甚至 jQuery 也省略了 hasOwnProperty 测试,并明确指出如果您使用滥用它的代码,它将失败。
  • non-enumerable properties don't exist in previous versions of Javascript.previous是指哪个版本?
  • @user1643156 ECMAScript 5.0 之前的任何内容
  • IE 6/7/8 仅支持 ECMAScript 3.0 (JavaScript 1.5)。所以我猜Object.defineProperty 不是我的问题的跨浏览器选项。
【解决方案2】:

另一种选择是调用一个方法,而不是定义为对象原型方法-

function doSomething(p) {
    this.innerHTML = "<em>"+p+"</em>";
    this.style.color = "#f00";
    alert(p);
};

//

doSomething.call(document.getElementById("foo"),"Hello World");

【讨论】:

    【解决方案3】:

    如果您向对象原型添加内容,您将失去使用for p in obj 的良好对象迭代功能,因为您添加的可枚举属性也会在所有对象上进行迭代

    例如:

    Object.prototype.doSomething = function(p) {
        this.innerHTML = "<em>bar</em>";
        this.style.color = "#f00";
        alert(p);
    };
    
    for (p in {foo:"bar"}){
        console.log(p);
    }
    
    //foo
    //doSomething
    

    出乎意料的是,您还将获得doSomething 登录。要解决此问题,您必须在迭代对象时添加hasOwnproperty 检查,但这里的风险是您可能会破坏其他不期望普通对象具有除文字中指定的属性之外的属性的代码.

    【讨论】:

    • 因为你已经添加了 enumerable 属性...
    • @Alnitak 已更新,谢谢。
    【解决方案4】:

    通常不是一个好主意。该函数现在可以在您应用中使用 Object 原型(很多)的 everything 上使用,并将显示在枚举 Object 原型的函数中。

    更好的选择是定义一个单独的原型:

    function MyObject {
        ...
    }
    
    MyObject.prototype.doSomething = function() {
        ...
    }
    
    var myObj = new MyObject();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 2016-09-23
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      相关资源
      最近更新 更多