在Global Scope上调用Object.prototype方法

Hos*_*aki 7 javascript

此代码抛出错误.

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

但是这段代码不会引发错误.

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

实例 | 直播源

就我而言,func(arg)等于this.func(arg)是否this为Global Object.为什么会发生这样的事情?

T.J*_*der 8

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

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

当你说

func();
Run Code Online (Sandbox Code Playgroud)

...浏览器所做的是func使用标准标识符解析查找,然后像调用它一样调用它:

func.call(undefined);
Run Code Online (Sandbox Code Playgroud)

如果func是松散模式函数,那么在调用中func,this是全局对象.但是,如果func是严格模式函数,则this在调用内undefined.

相比之下,有了这个:

this.func();
Run Code Online (Sandbox Code Playgroud)

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

this.func.call(this);
Run Code Online (Sandbox Code Playgroud)

在严格或松散模式下,这意味着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);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,除了定义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 | 直播源

<!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>
Run Code Online (Sandbox Code Playgroud)

输出(使用支持严格模式的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