“这个”指的是别的什么?

时间:2011-11-12 03:31:41

标签: javascript

当我运行此代码时:

var Test = function() {
    return this.stuff;
};

Test.stuff = 'Neat!';

document.write(Test() || 'Not neat.');

为什么我会'不整洁'?为什么我不能使用this.stuff访问stuff属性?

5 个答案:

答案 0 :(得分:5)

类方法和变量放在prototype属性上:

Test.prototype.stuff = 'Neat!'

构造函数(我假设这是你想要的,给定大写情况和this)应该用new运算符调用:

new Test()

并且它们不应返回值(您应该使用返回this的默认值)

function Test(){
    this.instanceVariable = 17;
    //no return!
}

至于你的真正需要,你可以直接访问该功能及其属性

function Test(){
    return Test.stuff;
}

但是,我并不是滥用像这样的命名空间函数的忠实粉丝。我更喜欢有一个命名空间对象来做事情

//in a real case I would probably use the module pattern for private variables
//but whatever...

var Namespace = {};

Namespace.stuff = 'Neat!';

Namespace.F = function(){
    console.log(Namespace.stuff);
};

答案 1 :(得分:5)

这就是你所做的:

var Test = function() {                //Test is a Function object
    return this.stuff;                 //this is a pointer to an object, not Test
};

Test.stuff = 'Neat!';                  //Add a property to Test

document.write(Test() || 'Not neat.'); //this has no property stuff

将代码的最后一行更改为:

document.write(Test.call(Test) || 'Not neat.'); //this now points to Test

您的代码无效的原因是因为this指针指向:

  1. 当函数调用以new关键字为前缀时创建的构造函数的实例。 (例如var foo = new Foo(); //the this in Foo points to foo [for the sake of explanation])。
  2. 传递给callapply的对象作为第一个参数。
  3. 您想要做的事情是:

    var Test = function Temp() {           //Test is a Function object, alias Temp
        return Temp.stuff;                 //Temp is the same as Test, only locally
    };
    
    Test.stuff = 'Neat!';                  //Add a property to Test
    
    document.write(Test() || 'Not neat.'); //writes Neat!
    

    如果您喜欢,请回复此答案。欢呼声。

答案 2 :(得分:3)

您从全局上下文中调用Test,因此this引用全局对象,因此this.stuff引用全局变量stuff undefined这是假的。这就是您看到"Not neat."

的原因

您可以将其显示为Neat!,如下所示:

请参阅http://jsfiddle.net/aYh5y/

window.stuff = 'Neat!';
var Test = function() {
    return this.stuff;
};
alert(Test() || 'Not neat.');

<强>附录

以下是一种让this作为封闭对象工作的方法:

var Test = function () {
    return this.stuff;
};

var example = {
    g: Test,
    stuff: "Pretty neat"
};

alert(example.g() || 'Not neat.');

我们在这里通过目标对象调用Test

http://jsfiddle.net/aYh5y/1/

答案 3 :(得分:3)

虽然其他人已经发布了为什么会发生这种情况(对this的理解不正确),但这是一个可靠的解决方案。

更新:正如Raynos在ECMAScript第5版中所指出的那样when using strict mode functions,使用arguments.callee无效(它会引发TypeError)。因此,如果使用这种方法,应该谨慎行事。 (当使用[正确] ECMAScript第5版引擎时,没有理由使用arguments.callee覆盖绑定到新范围的函数的名称 - 请参阅答案的结尾。)

var Test = function() {
   // arguments.callee is the current function, if any
   return arguments.callee.stuff
}
Test.stuff = 'Neat!'
alert(Test() || 'Not neat.') // Neat!

另一个是使用闭包:

var Test = (function () {
  function fn () {
    // closure over fn, which names this function-object
    return fn.stuff
  }
  fn.stuff = 'Neat!' // here
  return fn          // do not combine with function declaration!
})()
Test.stuff = 'Neat!' // or here
alert(Test() || 'Not neat.') // Neat!

或者,直接关闭变量:

var Test = (function () {
  var stuff = 'Neat!'
  return function () {
    // variable closure, no property
    return stuff
  }
})()
alert(Test() || 'Not neat.') // Neat!

或......有很多方法。

快乐的编码。


Aadit M Shah指出的另一种方法是使用函数标识符来引用当前函数:

var Test = function Temp () {
   return Temp.stuff
}
Test.stuff = 'Neat!'
alert(Test() || 'Not neat.') // Neat! (But see below.)

正如Aadit指出的那样,根据ECMAScript 5th edition specification第99页,这是有效的:

  

可以从FunctionExpression的FunctionBody内部引用FunctionExpression中的标识符   允许函数以递归方式调用自身。但是,与FunctionDeclaration不同,FunctionExpression中的标识符不能被引用,也不会影响包含FunctionExpression的范围。

然而,某些浏览器(至少是IE9)错误地实现了这个(我不确定上面提到的行为是否在第3版中得到了明确定义)。考虑:

var x = function y () { return y }; y = 42; x();

在IE9中它将产生42,在FF8中它将产生函数对象。 IE9在这里不正确,因为它将y作为封闭范围内的变量引入,ECMAScript禁止该函数用于函数表达式。以下是这种不正确的实现如何导致不同结果的上下文示例:

var Test = function Temp () {
   return Temp.stuff
}
Test.stuff = "Neat!"
Temp = {}
alert(Test() || 'Not neat.') // 'Not neat.' in IE9, 'Neat!' in FF8

答案 4 :(得分:0)

stuff属性被分配给函数,但是从全局读取...这两个是单独的实体