Javascript对象如何工作
How do Javascript objects work?
前言
- 我知道这些示例的正确代码。
- 我想知道的是为什么以下示例无法按预期工作。
法典
-
调用函数时带括号
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); };
这将提醒"未定义未定义",为什么?
-
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); };
这将从字面上写下警报框上的功能,为什么?
提前谢谢你。
内联注释,下面的讨论,参考文献和进一步阅读:
-
调用函数时带有括号
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
"。您只需使用函数对象的名称来引用函数对象,无需
()
,例如:x = foo;
表示"将函数对象
foo
分配给x
。(然后你可以称之为:x()
。 -
与其他一些语言不同,在JavaScript中,
this
完全由函数的调用方式定义,而不是定义函数的位置。当你通过自由变量(例如,foo()
(调用函数时,你没有做任何事情来显式设置函数调用的this
,因此this
将是默认值,即全局对象(浏览器上window
(。您可以通过两种不同的方式设置
this
:A. 将函数引用放在对象属性上,并通过属性对它的引用调用函数,例如:
// 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;
然后,您将通过属性调用它:
this.thought(); x.thought();
在函数调用中,
this
将引用从中检索属性的对象。B. 使用函数对象的固有
call
或apply
函数:sayIt.call(lemon);
表示"调用
sayIt
函数,使this
= 函数调用中的lemon
"。如果将进一步的参数传递给call
,它们将被传递给函数,因此:sayIt.call(lemon, 1, 2, 3);
表示"使用
this
=lemon
调用sayIt
并传入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);
表示"使用
this
=lemon
调用sayIt
并传入1
、2
和3
。
我已经写了一些关于这些主题的博客,FWIW:
- 神话般的方法
- 你必须记住
this
- 匿名匿名(更多地讨论函数引用和分配它们(
更多探索:
- ECMAScript 规范(是的,真的(
- MDC 的 JavaScript 页面
- Crockford的JavaScript页面(高级,首先阅读并理解以上所有内容(
我假设第一个示例中有拼写错误,您打算写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
,因此它将打印源代码。
第一个代码:
编辑注意:编辑以反映问题中的编辑
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
};
我认为您在第一个例子中有一个错误。你写了alert(lemon.sayIt);
它应该alert(lemon.thought);
的地方.无论如何。。。
调用函数时带括号
sayIt
。这将提醒"未定义未定义",为什么?
因为当你执行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())
。
我建议你阅读
- 功能
- 使用对象
根据您的代码,"lemon"对象具有属性"type"、"taste"和"thought"。
alert(lemon.sayIt);
此行提醒"lemon"上的"sayIt"属性的值,转换为字符串。由于"lemon"对象没有"sayIt"属性,因此它将未定义的值转换为字符串并显示它。
alert(lemon.thought);
此行提醒 "lemon" 上的 "thought" 属性的值,转换为字符串。由于 "thought" 属性是一个函数,因此字符串转换显示函数的文本。
您可能想要做的是调用该函数,并显示其返回值: alert(lemon.thought(((;
-
函数 say它是在调用它之后定义的。 将sayIt的定义移到水果的定义之上就可以解决了问题。
-
你正在提醒函数的定义,而不是调用该函数的返回值。
说它不是 Fruit 对象的函数 - 它是窗口对象的函数。
Fruit.thought是一个函数,或者是一个"函数指针",因为它被分配给window.sayIt函数。
- Javascript:selenium Web驱动程序isDisplayed()不工作
- jQuery UI自动完成突然停止工作
- AngularJS UI路由器不能像ng路由器那样工作
- HTML5音频加载和播放获胜'我不能在iPad上工作
- JavaScript打印功能使日历停止工作
- Javascript.getHours()工作不正常
- 为什么这在IE中的工作方式与在Firefox中不同
- 视频HTML没有'无法在Internet Explorer 11上工作
- 扩展移相器按钮类不工作
- Firebase迁移-简单的Firebase.set没有'不再工作了——旧的还是新的
- 谷歌地图不是以HTML显示,而是在JS Fiddle上工作
- 正在尝试使用if和else添加类,但无法正常工作
- Jquery FadeIn FadeOut 只工作一次
- Foreach无法在Typescript中工作
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- 为什么不是't窗口.恢复正常工作吗?(javascript/jquery)
- 最大高度转换不;不工作,工作缓慢
- Gulp-rev:不是第一次工作,而是在第一次工作之后工作
- 在JavaScript中的类中,push和concat的工作方式有何不同
- JQuery - Ajax: encodeUriComponent不工作(EncodeUri工作)