[英]How do Javascript objects work?
With parentheses when calling sayIt
function.调用
sayIt
function 时带括号。
function Fruit(type){ this.type = type; this.taste = "Awful"; this.thought = sayIt(); } function sayIt(){ return this.taste+" "+ this.type; } window.onload = function (){ var lemon= new Fruit("Lemon"); alert(lemon.thought); };
This will alert "undefined undefined", why?这会提示“未定义未定义”,为什么?
sayIt
function without parentheses. sayIt
不带括号。
function Fruit (type){ this.type = type; this.taste = "Awful"; this.thought = sayIt; } function sayIt(){ return this.taste +" "+ this.type; } window.onload = function (){ var lemon= new Fruit("Lemon"); alert(lemon.thought); };
This will literally write down the function on the alert box, why?这实际上会在警告框中写下 function,为什么?
Thank you in advance.先感谢您。
Notes inline, discussion below, references and further reading at the end:内联注释,下面的讨论,最后的参考和进一步阅读:
With parentheses when calling sayIt
function.调用
sayIt
function 时带括号。
function Fruit(type){ this.type = type; this.taste = "Awful"; // Here, you're *calling* the `sayIt` function and assigning its // return value to `this.thought`. During the call, `this` will // refer to the global object (not to the `Fruit` instance). this.thought = sayIt(); } function sayIt(){ // If this is called as it is above, `this` is the global object, // which is `window` in browsers. Since `window` doesn't have // `taste` or `type` properties, this returns "undefined undefined". // That's what `this.thought` above receives. return this.taste+" "+ this.type; } window.onload = function (){ var lemon= new Fruit("Lemon"); // You've said this alerts "undefined undefined", but I think you'll // find it just alerts "undefined" (singular). There is no `sayIt` // property on the `lemon` instance at all. If you alerted // `lemon.thought` instead, you'd see the "undefined undefined" we // stored there above. alert(lemon.sayIt); };
sayIt
function without parentheses. sayIt
不带括号。
function Fruit (type){ this.type = type; this.taste = "Awful"; // Here you're assigning the `sayIt` function to `this.thought`. // Perfectly normal stuff. this.thought = sayIt; } function sayIt(){ return this.taste +" "+ this.type; } window.onload = function (){ var lemon= new Fruit("Lemon"); // Here you're also *referring* to the function object, not calling // it. (To call a function, you use `()` after it.) So since functions // are objects, you're passing an object reference into `alert`. // Alert will try to convert that to a string, and the // implementation of `toString` on `Function` objects in most // environments is to dump out a version of the source code of // the function (although this behavior is *not* standardized and // some browsers, esp. mobile browsers, don't do it). alert(lemon.thought); };
Key concepts from the above:上述关键概念:
Functions are objects.函数是对象。 You call a function by using a reference to it followed by
()
, eg:您通过使用对它的引用后跟
()
来调用function ,例如:
x = foo();
means "call foo
and assign its return value to x
".表示“调用
foo
并将其返回值分配给x
”。
You refer to the function object by just using its name, sans ()
, eg:您只需使用其名称sans
()
即可引用function object ,例如:
x = foo;
means "assign the function object foo
to x
. (You could then call it: x()
.)表示“将 function object
foo
分配给x
。(然后你可以称之为: x()
。)
Unlike some other languages, in JavaScript, this
is defined entirely by how a function is called , not where it's defined .与其他一些语言不同,在 JavaScript 中,
this
完全由function 的调用方式定义,而不是定义在哪里。 When you call a function via a free variable (eg, foo()
), you're doing nothing to explicitly set the this
for the function call, and so this
will be the default value, which is the global object ( window
on browsers). When you call a function via a free variable (eg,
foo()
), you're doing nothing to explicitly set the this
for the function call, and so this
will be the default value, which is the global object ( window
on browsers )。
You can set what this
is in two different ways:您可以通过两种不同的方式设置
this
是什么:
A. Put the function reference on an object property and call the function via the property's reference to it, eg: A. 将 function 引用放在 object 属性上,并通过属性对它的引用调用 function,例如:
// To put it on whatever `this` is at the moment: this.thought = sayIt; // Or to put it on an object we have in the variable `x`: x.thought = sayIt;
You'd then call it via the property:然后你可以通过属性调用它:
this.thought(); x.thought();
Within the function call, this
will refer to the object from which you retrieved the property.在 function 调用中,
this
将引用您从中检索属性的 object。
B. Using the function object's intrinsic call
or apply
functions: B. 使用 function 对象的内部
call
或apply
函数:
sayIt.call(lemon);
means "call the sayIt
function, making this
= lemon
within the function call."意思是“在 function 调用中调用
sayIt
function,使this
= lemon
。” If you pass further arguments to call
, they'll be passed to the function, so:如果您将进一步的 arguments 传递给
call
,它们将被传递给 function,因此:
sayIt.call(lemon, 1, 2, 3);
means "call sayIt
with this
= lemon
and pass in 1
, 2
, and 3
.意思是“用
this
= lemon
调用sayIt
并传入1
、 2
和3
。
There's also the apply
function, which is just the same thing except you pass the arguments as an array rather than individually:还有
apply
function,除了您将 arguments 作为数组而不是单独传递之外,这是一样的:
// note ------------v-------v---- the square brackets create an array sayIt.applyl(lemon, [1, 2, 3]); // More explicitly: var a = [1, 2, 3]; sayIt.apply(lemon, a);
means "call sayIt
with this
= lemon
and pass in 1
, 2
, and 3
.意思是“用
this
= lemon
调用sayIt
并传入1
、 2
和3
。
I've blogged a bit on these subjects, FWIW:我写了一些关于这些主题的博客,FWIW:
this
this
More to explore:更多探索:
I'm assuming there is a typo in the first example and you meant to write alert(lemon.thought())
.我假设第一个示例中有错字,您打算编写
alert(lemon.thought())
。 The reason you're seeing undefined undefined
is because this.thought
is set to the return value of the sayIt
function.您看到
undefined undefined
的原因是this.thought
设置为sayIt
function 的返回值。 In the sayIt
function, this
refers to the window
object and not the Fruit
object.在
sayIt
function 中, this
是指window
object 而不是Fruit
ZA8CFDE6331BD54B66AC96F8911C。 Since window
doesn't have a taste
or type
property, you will see undefined undefined
.由于
window
没有taste
或type
属性,您将看到undefined undefined
。
In the second example (I'll again assume you have a typo and you meant to do alert(lemon.thought())
), you this.thought
is set to be a reference to the sayIt
function, so you're not actually calling it.在第二个示例中(我将再次假设您有错字并且您打算执行
alert(lemon.thought())
),您this.thought
设置为对sayIt
function 的引用,所以您实际上并不是调用它。 When you alert a reference to a function, it will print out the source of that function.当您警告对 function 的引用时,它将打印出该 function 的来源。
BONUS奖金
You can get it to work the way you want if you do this:如果你这样做,你可以让它以你想要的方式工作:
this.thought = sayIt.call(this);
This will set the this
to point to the Fruit
object and now sayIt
will return what you want.这会将
this
设置为指向Fruit
sayIt
现在说它将返回您想要的。
In the second example, you will get what you want if you do this:在第二个例子中,如果你这样做,你会得到你想要的:
alert(lemon.thought());
lemon.thought
refers to sayIt
and the this
will be set properly because you are calling a member function of lemon
. lemon.thought
指的是sayIt
并且this
将被正确设置,因为您正在调用lemon
的成员 function 。
The first argument to call
(or its friend apply
) is for the value of this
in the context of that function. call
(或其朋友apply
)的第一个参数是在 function 的上下文中this
的值。
UPDATE更新
Dan, in the second example even without the change I made, that is if you still have lemon.thought = sayIt;
丹,在第二个例子中,即使没有我所做的改变,也就是说,如果你还有
lemon.thought = sayIt;
and you say alert(lemon.thought);
你说
alert(lemon.thought);
. . You will still get the source of the function because you're not calling the function and passing its result to
alert
.您仍将获得 function 的来源,因为您没有调用 function 并将其结果传递给
alert
。 You're passing the function reference itself to alert
, and so it will print the source.您将 function 引用本身传递给
alert
,因此它将打印源代码。
First code:第一个代码:
EDIT NB: edited to reflect edits in the question编辑注意:编辑以反映问题中的编辑
function Fruit(type){
this.type = type;
this.taste = "Awful";
this.thought = sayIt(); // this line invokes sayIt, with global context,
// so sets thought to 'undefined undefined'
}
function sayIt() {
return this.taste+" "+ this.type; // as called, this == window, not the Fruit object
}
window.onload = function() {
var lemon= new Fruit("Lemon");
alert(lemon.thought); // see above
};
Second code:第二个代码:
function Fruit (type){
this.type = type;
this.taste = "Awful";
this.thought = sayIt;
}
function sayIt(){
return this.taste +" "+ this.type;
}
window.onload = function (){
var lemon= new Fruit("Lemon");
alert(lemon.thought); // doesn't -call- the function, results in .toString() on
// the function object
};
I think you have a mistake in the first example.我认为你在第一个例子中有一个错误。 You wrote
alert(lemon.sayIt);
你写了
alert(lemon.sayIt);
where it should be alert(lemon.thought);
应该在哪里保持
alert(lemon.thought);
. . Anyway...
反正...
With parentheses when calling
sayIt
function.调用
sayIt
function 时带括号。 This will alert "undefined undefined", why?这会提示“未定义未定义”,为什么?
Because when you execute this.thought = sayIt();
因为当你执行
this.thought = sayIt();
, you are assigning the return value of sayIt
to this.thought
. ,您将
sayIt
的返回值分配给this.thought
。 When you call sayIt()
, then this
inside the function will refer to the global object which is window
is browser.当您调用
sayIt()
时, function 中的this
将引用全局 object ,即window
是浏览器。 And window.taste
and window.type
are not defined.并且
window.taste
和window.type
没有定义。 Hence this.thought
will have string "undefined undefined"
assigned to it.因此
this.thought
将分配给它的字符串"undefined undefined"
。
sayIt
function without parentheses.sayIt
不带括号。 This will literally write down the function on the alert box, why?这实际上会在警告框中写下 function,为什么?
In this case you are assigning a reference to the function itself to this.tought
.在这种情况下,您将对 function 本身的引用分配给
this.tought
。 The string representation of a function is the code itself. function 的字符串表示是代码本身。 Now you can call the function via
lemon.tought()
.现在您可以通过
lemon.tought()
调用 function 。 If you do so, this
will refer to the lemon
object and the output will be as expected.如果这样做,
this
将指的是lemon
object 和 output 将如预期的那样。
So, call the function: alert(lemon.tought())
.所以,调用 function:
alert(lemon.tought())
。
I suggest you read about我建议你阅读
Based on your code, the "lemon" object has the properties "type", "taste", and "thought".根据您的代码,“柠檬” object 具有“类型”、“味道”和“思想”属性。
alert(lemon.sayIt);
This line alerts the value of the "sayIt" property on "lemon", converted to a String.此行警告“lemon”上的“sayIt”属性值,转换为字符串。 Since the "lemon" object doesn't have a "sayIt" property, it converts the value undefined to a string and displays it.
由于 "lemon" object 没有 "sayIt" 属性,它将undefined的值转换为字符串并显示出来。
alert(lemon.thought);
This line alerts the value of the "thought" property on "lemon", converted to a String.此行警告“lemon”上的“thought”属性的值,转换为字符串。 Since the "thought" property is a function, the string conversion displays the text of the function.
由于“thought”属性是 function,因此字符串转换显示 function 的文本。
What you probably want to do is call the function, and display its return value: alert(lemon.thought());您可能想要做的是调用 function,并显示其返回值:alert(lemon.thought());
The function sayIt is defined after it is called. function 说它是在调用后定义的。 Moving the definition of sayIt above the definition of fruit would fix.
将 sayIt 的定义移到fruit 的定义之上可以解决问题。
You're alerting the definition of a function and not the return value from calling that function.您正在提醒 function 的定义,而不是调用 function 的返回值。
sayIt is not a function of the Fruit object - it's a function of the window object. sayIt is not a function of the Fruit object - it's a function of the window object.
Fruit.thought is a function, or a "function pointer" as it is assigned to the window.sayIt function. Fruit.thought 是 function 或“函数指针”,因为它被分配给 window.sayIt function。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.