16

可能重复:
Javascript:我是否需要为对象中的每个变量放置 this.var?

我正在努力理解 javascript 中的函数和对象。据说函数也是对象,对象是一种“关联数组”,即键值对的集合。我明白,如果我写

function myFunction() {
    var value = 0;
}
alert(myFunction.value); //then this gives me "undefined"

因为变量具有函数范围。但如果我写

function myFunction() {
    this.value = 0;
}
alert(myFunction.value); //then this gives me "undefined" too.

但最后,如果我写

function myFunction() {
    this.value = 0;
}
myFunction.value = 0;
alert(myFunction.value); //then this gives me 0

所以我可以给 myFunction 属性“值”,但来自“外部”。有人可以解释发生了什么以及为什么 this.value = 0; 不会创造财产“价值”。

4

6 回答 6

13

让我们分别看一下所有三种情况:

function myFunction()
{
    var value = 0;
}

在这里,您要在函数的范围内声明一个变量。每次调用函数时,都会创建变量(并分配内存)。当函数返回时,变量超出范围 - 变量value被标记并将被 GC'ed。不能从比此函数范围“更高”的范围访问范围...如果此函数在其范围内定义了一个函数,则该函数将有权访问该变量value(查看闭包以获取更多详细信息)。底线:该变量仅在调用函数时存在,并且在函数返回后不存在。

function myFunction()
{
    this.value = 0;
}

在这里,您定义的函数可以是构造函数、方法、事件处理程序或以上所有内容的组合。this是一个引用,它将指向调用函数的上下文。此上下文是“临时”确定的,并且可能会有所不同:

myFunction();// global scope, this points to window
var anObject = {method: myFunction};
anObject.method();//called in the object's context, this points to object
console.log(abObject.value);//logs 0
var instance = new myFunction();//as constructor
console.log(instance.value);//logs 0
document.getElementById('anInputField').onclick = myFunction;//on click, value will be set to 0

在最后一种情况下:

function myFunction()
{
    this.value = 0;
}
myFunction.value = 0;

如果你写这个不会有任何区别:

function myFunction()
{}
myFunction.value = 0;

因为,正如我上面解释的:this引用函数调用时的任何上下文。事实上,这不一定是myFunction:通常不会是:

var anObject = {method: myFunction};
myFunction.value = 101;//myFunction.value is changed
anObject.method();
console.log(anObject.value);//0 -> the function still sets the value property to 0

如果要访问该函数内部的函数属性,最简单的方法是像引用任何其他对象一样引用该函数:

function myFunction()
{
    this.value = myFunction.value;
}
myFunction.value = 101;

警告:只是一个友好的警告:在不检查全局变量的情况下在函数
中使用不是很安全...如果在没有显式上下文的情况下调用函数,JS默认使用全局 ( ) 对象。这意味着将属性分配给碰巧指向的任何对象的每一行都将设置一个全局变量:thiswindowthis

function myFunction()
{
    this.foo = 'bar';
}
myFunction();
console.log(window.foo);//logs bar EVIL GLOBAL

防止全局对象被全局变量弄乱的几种方法:

function mySafeFunction()
{
    'use strict';//throws errors, check MDN
    //this defaults to null, instead of window
    impliedGlobal = 'Error';//doesn't work
    this.onGlobal = 'Error';//null.property doesn't work
}
//same goes for constructors, but a more precise check can be used, too (and works on older browsers)
function SafeConstructor()
{
    if (!(this instanceof SafeConstructor))
    {//this doesn't point to SafeConstructor if new keyword wasn't used
        throw new Error('Constructor wasn\'t called with new keyword');
        //or "correct" the error:
        return new SafeConstructor();
    }
    console.log(this);// will always point to the SafeConstructor object
}
于 2012-11-21T19:16:34.153 回答
7

您需要instance使用new关键字创建一个。

function myFunction() {
    this.value = 0;
}

var inst1 = new myFunction();

alert(inst1.value);  // this works

现在 this 对应于当前 object ,它会为您提供相应的属性值。

检查小提琴

在一天结束时..函数仍然是对象..所以当你分配它时它不会抱怨..当你在函数内部和外部使用值(键)myFunction.value = 0时可能会令人困惑..将它替换为

myFunction.abc = 'Hello' 
alert(myFunction.abc) still works

但它不会反映在实际的 myFunction 中,因为您还没有调用该函数。

于 2012-11-21T18:55:20.687 回答
3

您误解了 javascript 原型/对象概念。

对于第一个示例,您是对的,该变量具有函数范围

第二个例子是错误的。如果要将函数用作“类”,则必须从中创建一个对象

function myFunction() { this.value = 0; }
var test = new myFunction;

只有这样你才能访问它的“价值”属性。对于每个“新”语句,都会创建一个新对象。

在第三个示例中,您向函数添加静态属性,无需创建对象即可访问该属性。不同的技术

希望它有所帮助

于 2012-11-21T18:58:20.443 回答
2

不确定我是否可以为您清除所有细微差别,但这可能会有所启发:

function myFunction() {
    this.value = 0;
}
alert( (new myFunction).value);

使用new关键字创建一个myFunction允许this用于从函数内部分配值的新“实例”。

于 2012-11-21T18:55:30.550 回答
1

myFunction是一个函数对象。您可以传递它,将其分配给变量,为其分配属性,然后您可以调用它。

分配属性的工作方式与任何其他对象一样:

myFunction.value = 0;

但请注意,此时您还没有调用该函数,因此函数(或)内部的代码甚至还没有执行。考虑一下:var value = 0;this.value = 0;

function someFunction() {
    window.foo = 'foo'; // create a global variable
}

someFunction.bar = 'bar';

console.log(someFunction.bar); // 'bar'
console.log(window.foo); // undefined

someFunction(); // execute the function

console.log(someFunction.bar); // 'bar'
console.log(window.foo); // 'foo'

当您使用 执行函数时myFunction(),才会创建局部变量/设置属性this。指的是什么this取决于函数的调用方式,并且在 MDN 文档中有很好解释除非您明确设置它,否则this 永远不会引用函数本身。

于 2012-11-21T19:09:27.483 回答
1

在 javascript 中,任何函数也是一个对象,它们是 的对象Function,就像Number, Object, Array

一个棘手的事情是new单词,然后它在函数之前添加前缀,它创建一个新对象,并使this关键字指针指向该新对象(另外,它将该函数原型分配给新对象 __ proto __)。
在功能上,

this.value = 0;

将为新对象创建一个新属性value,并将 0 分配给它。

如果没有 newbefore 函数,它是函数调用,并且this会指向Window对象。

尝试console.dir(this);在函数中,你会看到不同。

myFunction.value = 0;

将创建属性valuemyFunction并将 0 分配给它。因为 myFunction 只是一个对象(的Function)。

于 2012-11-21T19:26:26.267 回答