4

在创建自定义对象时,给它提供覆盖本机 js 函数的方法(在我目前的情况下是“读取”、“写入”和“保存”)是否安全?

有问题的对象永远不必写入 DOM(或以其他方式使用它将丢失的函数);这些方法名称很理想,所以我很好奇,然后惊讶地发现很难找到一个明确的答案。下面的例子。谢谢。

/**
 * Ticket class
 * @param category
 * @param issuedBy
 * @param reissuable If true, lock cannot be overridden by the same method that locked it
 * @returns {Ticket}
 * @constructor
 */
Ticket = function (category, issuedBy, reissuable) {
    //properties
    this.id = Date.now().toString();
    this.category = category;
    this.resolved = false;
    this.issuingMethod = issuedBy;
    this.reissuable = reissuable === true;
    this.data = {};

    //methods
    this.resolve = function () { return this.resolved = true;};
    this.read = function (dataPath) { // find dataPath in this.data }
    this.write = function (dataPath, value) { // add value to dataPath of this.data}

    return this;
};
4

2 回答 2

4

这并不完全安全。当你的构造函数被调用时newthis指向全局对象。

var ticket = Ticket(); //this.document will point to the global document object

理解你的代码的关键是它使用this了一个特殊的关键字,可以表示不同的东西;

  • 不在函数内时,表示window( <script>alert(this.name)</script>)
  • 当作为没有附加对象的独立函数调用时, ( alert())this指向window对象
  • 使用点语法调用时(ticket.resolve()),指向点 ( )this左侧的对象。ticket
  • 当作为构造函数 ( new Ticket) 调用时,this它是一个新的空对象,Ticket.prototype在其原型链中。
  • 当从内联 HTML handlers( onclick="alert(this.id)") 调用时,this指向附加事件的 HTML 元素
  • 当从和 AJAX 回调等函数调用时,setTimeout通常指向setIntervalthiswindow
  • 当使用applyor调用函数时call,您可以指定this将是什么
  • 你通常可以Function.bind用来确保你的函数被正确调用

在调用的情况下var ticket = Ticket(),您的所有代码this.name = 'something'都将创建或覆盖现有的全局变量,在这种情况下,name是窗口的。

如果您关心此问题,则可以通过执行以下操作来缓解此问题。

    Ticket = function (category, issuedBy, reissuable) {
    if (!this instanceof Ticket) { // called as a function
         return new Ticket(category, issusedBy, reissuable);
    }
    //properties
    this.id = Date.now().toString();

要以通用方式执行此操作,您可以查看此链接http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

请注意,这可能是不必要的样板代码,可以通过遵循代码约定并强制执行它们来避免

于 2014-05-13T23:00:20.567 回答
2

在提供的代码示例中,您没有覆盖任何本机Object.prototype方法。Object.prototype但是,如果您不小心,您可能会覆盖继承自的本机方法。

function MyObject() {}

MyObject.prototype.hasOwnProperty = function () { return true; };

new MyObject().hasOwnProperty('test'); //true

显然这会产生误导,在这种情况下,我会选择在您的域中具有类似含义的另一个函数名称,而不是覆盖本机Object.prototype.hasOwnProperty函数。

在另一个答案中已经说过,在没有new关键字的情况下调用构造函数也可能会覆盖全局本机变量。虽然这是非常正确的,但与仅潜在地覆盖本地全局变量相比,它会产生更多的负面影响。使用 JSHint 之类的出色工具对代码进行 linting(就像您应该做的那样)将避免这些错误。

于 2014-05-13T22:57:16.897 回答