JavaScript严格模式下“this”的行为不一致

时间:2012-09-03 15:26:45

标签: javascript this strict

更新

为了清楚起见:@FelixKing:是的,我希望在调用this时仍然未定义window.foo(),这就是原因:因为,在JavaScript中:

function foo()
{
    console.log('I am a function');
}

几乎)与:

相同
var foo = function()
{
    console.log('I am a function');
}

foo === window.foo评估为true,我希望它们的行为都相同。如果函数是变量,并且JS回退到全局对象(在函数x内部,没有声明变量但是你使用它,JS 起泡直到所有作用域,直到全局对象,直到它找到有问题的变量,或者它在全局级别创建它),如果预先指定window对象则无关紧要。然而,当你这样做时,行为会发生变化,这是我没想到的。我有一个直觉为什么会这样(我正在定义方法,而不是变量)但是,对于全球物体,它们之间几乎没有差别。 var c = 'Variable'; console.log(window.c === c);记录为真等等......但我想知道实际上是什么,以及它是如何工作的(在所有级别上)。

我已准备好接受foo.apply(this,[]);foo.apply(window,[]);允许您强制this指向全局对象,而不是window.foo();。如果要严格保护全球物体,我会说这会让后门敞开。例如,我偶尔会发现自己调用函数,具体取决于变量的值。为此我使用window[myVar]();,严格与否,这意味着this 指向全局对象,而如果我直接调用该函数则不会。就我而言,这是一种不一致。


我在严格模式下使用this关键字遇到了一些奇怪的行为。不要误会我的意思我知道thisundefined in strict functions。令我感到困惑的是,this可以被强制指向全局对象(或任何其他对象),有效地破坏了严格模式提供的安全网。这也有其他含义。请考虑以下代码:

'use strict';//using strict everywhere
(function(Global)
{
    var closureObject = {};
    Global.foo = function()
    {
        closureObject.setIn = closureObject.setIn || 'Set in foo';
        console.log(this);
        console.log(this === Global);
        bar();
        bar.apply(this);
        return (this !== Global ? this : undefined);
    };
    Global.bar = function()
    {
        closureObject.setIn = closureObject.setIn || 'set in bar';
        console.log(this);
        return (this !== Global ? this : undefined);
    };
})(this);
var undef = (Math.ceil(Math.random()*10)%2 ? foo() : bar());
foo();//undefined --- false​​​​​​​​​​​​​​​​​ --- undefined --- undefined
window.foo();//Window --- true --- undefined --- window
foo.apply(this,[]);//same as window.foo

同样适用于自定义对象:

function Foo(n)
{
    this.name = n;
}
Foo.prototype.func = foo;//or window.foo
//other objects:
var d = new Date();
foo.apply(d,[]);//Date --- false --- undefined --- date

在我看来,这可能是黑客和陷阱的根源。更重要的是:它很难确定调用的来源:如果从全局对象(foo())调用window.foo();,那么该上下文当然不会传递给{{1} },除非使用bar

调用bar

我之所以想要切割&确定调用者上下文的干燥,安全和可靠的方法很简单:我使用闭包来避免那些讨厌的全局变量,但同时我设置了几个函数作为事件处理程序。
我知道不使用严格模式,或者设置全局是容易修复的,但是严格的模式仍然存在,我喜欢它给聚会带来的东西(好吧,大部分)。我坚信这就是JS将要发展的方式,我不愿意发现自己因为不想打扰bar.apply(this,[]);而烦恼我自己的代码。这可能不会太快发生,但我只是想让我的知识保持最新。

我已经阅读了strict上的MDN页面,以及John Resig的博文,我看了很多DC的视频,并阅读了很多他的文章,我还没有找到明确的我上面描述的行为的解释。我没有读完整个ECMAScript标准(男孩,那东西太干了,它可能会耗尽撒哈拉沙漠),但也许这里有人可以指出我正确的方向来帮助我更好地理解这一点。

1 个答案:

答案 0 :(得分:2)

我不确定我是否正确地阅读了您的问题,但似乎您在func.apply(context, arguments)可以将context作为参数的事实上遇到麻烦在函数内部由this引用。

我认为传递上下文是必要的,如果没有它,JavaScript就无法正常工作。

从头到尾,因为没有super正确使用继承的唯一方法就是使用像BaseClass.prototype.baseFunction.apply(this, arguments)这样的东西。

删除该功能会创建一种与当今JavaScript非常不同的语言,而不是strict模式的语言。