在调用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);
};
这会提醒“undefined undefined”,为什么?
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);
};
这会在警告框中写下这个函数,为什么?
提前谢谢。
答案 0 :(得分:4)
注释内联,下面的讨论,参考资料以及最后的进一步阅读:
在调用sayIt
函数时使用括号。
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 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);
};
以上的关键概念:
功能是对象。您通过使用对()
的引用,然后x = foo();
来调用函数,例如:
foo
表示“致电x
并将其返回值指定给()
”。
仅使用 sans x = foo;
的名称将引用到函数对象,例如:
foo
表示“将函数对象x
分配给x()
。(然后您可以调用它:this
。)
与其他一些语言不同,在JavaScript中,foo()
完全由如何调用函数定义,而不是定义。当您通过自由变量(例如this
)调用函数时,您无法为函数调用显式设置this
,因此window
将是默认值,这是全局对象(浏览器上的this
)。
您可以通过两种不同的方式设置// 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;
:
一个。将函数引用放在object属性上,并通过属性对它的引用来调用函数,例如:
this.thought();
x.thought();
然后您可以通过该属性调用它:
this
在函数调用中,call
将引用从中检索属性的对象。
B中。使用函数对象的内在apply
或sayIt.call(lemon);
函数:
sayIt
表示“调用this
函数,在函数调用中生成lemon
= call
。”如果你将其他参数传递给sayIt.call(lemon, 1, 2, 3);
,它们将被传递给函数,所以:
sayIt
表示“使用this
= lemon
致电1
并传入2
,3
和apply
。
还有// 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);
函数,除了将参数作为数组而不是单独传递之外,这是一回事:
sayIt
表示“使用this
= lemon
致电1
并传入2
,3
和{{1}}。
我在博客上写了一些关于这些主题的内容,FWIW:
this
更多探索:
答案 1 :(得分:3)
我假设第一个例子中有拼写错误,你打算写alert(lemon.thought())
。您看到undefined undefined
的原因是因为this.thought
设置为sayIt
函数的返回值。在sayIt
函数中,this
引用window
对象而不是Fruit
对象。由于window
没有taste
或type
属性,因此您会看到undefined undefined
。
在第二个例子中(我再次假设你有一个拼写错误而你打算做alert(lemon.thought())
),你this.thought
被设置为对sayIt
函数的引用,所以你实际上并没有打电话给它。当您提醒某个功能的引用时,它将打印出该功能的来源。
<强>奖金强>
如果你这样做,你可以按照你想要的方式工作:
this.thought = sayIt.call(this);
这会将this
设置为指向Fruit
对象,现在sayIt
将返回您想要的内容。
在第二个例子中,如果你这样做,你将得到你想要的东西:
alert(lemon.thought());
lemon.thought
引用sayIt
,this
将被正确设置,因为您正在调用lemon
的成员函数。
call
(或其朋友apply
)的第一个参数是该函数上下文中this
的值。
<强>更新强>
Dan,在第二个例子中,即使没有我做出的改变,也就是说,如果你仍然有lemon.thought = sayIt;
而你说alert(lemon.thought);
。您仍将获得该函数的源代码,因为您没有调用该函数并将其结果传递给alert
。您将函数引用本身传递给alert
,因此它将打印源。
答案 2 :(得分:2)
第一个代码:
编辑注意:已编辑以反映问题中的修改
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
};
第二段代码:
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
};
答案 3 :(得分:1)
我认为你在第一个例子中有一个错误。您写了alert(lemon.sayIt);
,其中应该是alert(lemon.thought);
。总之...
在调用
sayIt
函数时使用括号。这会提醒“undefined undefined”,为什么?
因为当您执行this.thought = sayIt();
时,您要将sayIt
的返回值分配给this.thought
。当您调用sayIt()
时,函数内的this
将引用window
为浏览器的全局对象。 window.taste
和window.type
未定义。因此,this.thought
将为其分配字符串"undefined undefined"
。
sayIt
函数没有括号。这将在警报框中写下函数,为什么?
在这种情况下,您要将对函数本身的引用分配给this.tought
。函数的字符串表示形式是代码本身。现在,您可以通过lemon.tought()
调用该函数。如果您这样做,this
将引用lemon
对象,输出将按预期进行。
所以,调用函数:alert(lemon.tought())
。
我建议你阅读
答案 4 :(得分:0)
根据您的代码,“lemon”对象具有“type”,“taste”和“thought”属性。
alert(lemon.sayIt);
此行警告“lemon”上的“sayIt”属性的值,转换为String。由于“lemon”对象没有“sayIt”属性,因此它将值 undefined 转换为字符串并显示它。
alert(lemon.thought);
此行警告“lemon”上的“思想”属性的值,转换为字符串。由于“思想”属性是一个函数,字符串转换显示函数的文本。
您可能想要做的是调用该函数,并显示其返回值: 警报(lemon.thought());
答案 5 :(得分:0)
函数sayIt在调用后定义。将sayIt的定义移到水果定义之上将会解决。
您正在警告函数的定义,而不是调用该函数的返回值。
答案 6 :(得分:0)
sayIt不是Fruit对象的函数 - 它是window对象的函数。
Fruit.thought是一个函数,或者是指向window.sayIt函数的“函数指针”。