在Global Scope上调用Object.prototype方法

时间:2013-07-06 08:01:42

标签: javascript

此代码抛出错误。

try {
  alert(hasOwnProperty('window'));
} catch(e) {
  alert(e); // Type Error : can't convert undefined to object
}

但此代码不会引发错误。

try {
  alert(this.hasOwnProperty('window')); // true (if on browser)
} catch(e) {
  // through catch block
  alert(e);
}

Live Example | Live Source

据我所知,如果func(arg)是全局对象,则this.func(arg)等于this。为什么会发生这样的事情?

2 个答案:

答案 0 :(得分:8)

认为正在发生的事情是我们有严格模式代码和非严格模式代码的交互。事实上,当我挖出一个Firefox 3.6.15(不支持严格模式)的副本时,我没有使用我发布到你的问题的链接得到错误(它警告“真实”两次)。 / p>

您显示的代码显然是非严格的模式代码。但是hasOwnProperty浏览器的实现怎么样?我怀疑它是严格的,在支持严格模式的浏览器上。

当你说

func();

...浏览器的作用是使用标准标识符解析查找func,然后像执行此操作一样调用它:

func.call(undefined);

如果func是松散模式函数,那么在func的调用中,this是全局对象。 ,如果func是严格模式功能,则通话中的thisundefined

与此形成鲜明对比:

this.func();

...它再次查找func(这次通过使用原型链的属性解析),然后有效地执行此操作:

this.func.call(this);

在严格或宽松模式下,这意味着函数中的this将为this。 (当然,在全球范围内,this是全局对象。)

以下是使用我们可以看到的代码而非hasOwnProperty

的代码进行交互的示例
(function() {
  "use strict";

  window.strictFunction = function() {
    display("strictFunction: this === window? " +
            (this === window));
    display("strictFunction: typeof this: " +
            typeof this);
  };

})();

strictFunction();
strictFunction.call(undefined);

正如您所看到的,除了在strictFunction上定义window函数的位之外,这是松散的代码。然后我们从松散的代码中调用该函数两次。结果如下:

strictFunction: this === window? false
strictFunction: typeof this: undefined
strictFunction: this === window? false
strictFunction: typeof this: undefined

相反,如果我们使用松散函数执行此操作,结果是:

looseFunction: this === window? true
looseFunction: typeof this: object
looseFunction: this === window? true
looseFunction: typeof this: object

完整示例:Live Copy | Live Source

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Fun With Strict Interactions</title>
  <style>
    body {
      font-family: sans-serif;
    }
    p {
      margin: 0;
    }
  </style>
</head>
<body>
  <script>
    (function() {
      "use strict";

      window.strictFunction = function() {
        display("strictFunction: this === window? " +
                (this === window));
        display("strictFunction: typeof this: " +
                typeof this);
      };

    })();
    (function() {

      window.looseFunction = function() {
        display("looseFunction: this === window? " +
                (this === window));
        display("looseFunction: typeof this: " +
                typeof this);
      };

    })();

    display("Direct call:");
    strictFunction();
    looseFunction();

    display("<hr>Call with <code>.call(undefined)</code>:");
    strictFunction.call(undefined);
    looseFunction.call(undefined);

    display("<hr>Call with <code>.call(window)</code>:");
    strictFunction.call(window);
    looseFunction.call(window);

    function display(msg) {
      var p = document.createElement('p');
      p.innerHTML = String(msg);
      document.body.appendChild(p);
    }
  </script>
</body>
</html>

输出(使用支持严格模式的JavaScript引擎):

Direct call:
strictFunction: this === window? false
strictFunction: typeof this: undefined
looseFunction: this === window? true
looseFunction: typeof this: object
--
Call with .call(undefined):
strictFunction: this === window? false
strictFunction: typeof this: undefined
looseFunction: this === window? true
looseFunction: typeof this: object
--
Call with .call(window):
strictFunction: this === window? true
strictFunction: typeof this: object
looseFunction: this === window? true
looseFunction: typeof this: object

答案 1 :(得分:1)

问题是 context 之一。也就是说,本质上,函数内部的this值是什么时候被调用。

调用hasOwnProperty('window')没有上下文。这与此相同:

hasOwnProperty.call(undefined, 'window');

this.hasOwnProperty('window')与此相同:

hasOwnProperty.call(this, 'window');

第二行代码将具有您期望的输出(true),但第一行显然不起作用。