“怎么说?”;这";Javascript中的关键字是否在对象文本中执行操作?
我看到了,但我看不出它回答了以下问题 鉴于此代码:“怎么说?”;这";Javascript中的关键字是否在对象文本中执行操作?,javascript,Javascript,我看到了,但我看不出它回答了以下问题 鉴于此代码: var MyDate = function(date) { this.date = date; }; var obj1 = { foo: new Date(), bar: new MyDate(this.foo) // this.foo is undefined }; var obj2 = {}; obj2.foo = new Date(); obj2.bar = new MyDate(this.foo); /
var MyDate = function(date) {
this.date = date;
};
var obj1 = {
foo: new Date(),
bar: new MyDate(this.foo) // this.foo is undefined
};
var obj2 = {};
obj2.foo = new Date();
obj2.bar = new MyDate(this.foo); // this.foo is undefined
var obj3 = {
foo: new Date(),
bar: new MyDate(obj3.foo)
};
var obj4 = {};
obj4.foo = new Date();
obj4.bar = new MyDate(obj4.foo);
为什么前两次尝试都失败了,但最后两次成功了?如果
this
未绑定到当前对象文本,那么它绑定到了什么?在Javascript中,只有函数调用才能建立新的this
上下文。调用foo.bar()
时,在bar
函数中,此
将绑定到foo
;当您调用foo()
时,它内部的将绑定到窗口
。对象文本构造函数不是方法调用,因此它不会以任何方式影响此
;它仍然会引用它在对象文本之外引用的任何内容。我认为您可能缺少函数和对象文本之间的一个关键区别:
函数体在函数被调用之前不会被求值
这意味着this
的值取决于函数的调用方式。如果它作为对象上的方法调用(例如someObj.someFunc()
),则此
将指向函数体中的该对象。如果它作为独立函数调用(someFunc()
)。主体中的代码将继承调用者环境中的任何this
。但是无论哪种方式,定义函数时this
的值都无关紧要
而对象文字只是一个表达式;如果出现this
,并且它不在文本中包含的函数体中,那么它将是this
在该表达式出现的代码点处的值。this.foo
是未定义的,因为在所有示例中,this
指的是全局窗口
对象。此外,即使您尝试了obj1.foo
,它仍将返回undefined,因为在计算整个表达式之前尚未创建属性。请尝试以下方法:
var obj1 = {
foo: new Date(),
bar: function() {
return new MyDate( this.foo ); // will work
}
};
它之所以有效,是因为当您调用obj1.bar()
时,该对象已经创建完毕;因为您在一个函数中,这个
对象将引用当前对象。Javascript是一种后期绑定语言。事实上,现在已经很晚了。这个
不仅在编译时没有绑定,甚至在运行时也没有绑定(就像大多数其他后期绑定语言一样)。在javascript中,此
在调用期间绑定
绑定规则与大多数其他OO语言有很大的不同,这就是为什么它似乎让很多不熟悉javascript的人感到困惑的原因
基本上,在代码中使用this
的方式和位置不会影响this
的行为(无论它是独立函数还是对象文本等)。决定this
值的是如何调用函数
这些规则是:
1-当函数作为构造函数调用时,将创建一个新对象,并且此
将绑定到该对象。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
2-当被称为对象方法时,此
指方法所属的对象。基本上是最后一个点之前的名称。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
3-如果在任何函数外部使用或函数未作为方法调用,则此
引用全局对象。javascript规范没有给全局对象命名,只是说它存在,但对于浏览器来说,它传统上被称为window
。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
4-在事件处理程序(如onclick等)中此
指触发事件的DOM元素。或者对于与DOM无关的事件,如setTimeout
或XMLHTTPRequest
,此
引用全局对象。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
5-最后,当使用call()
或apply()
方法调用函数时,可以将此
重新分配给任何对象(谷歌“mdn function.prototype.call”)。这样,javascript中的任何对象都可以借用/窃取其他对象的方法。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
在现代javascript实现中,有了Function.bind()
,我们现在有了另一条规则:
6-函数还可以使用bind()
方法将此
显式绑定到对象。bind
方法返回函数的新实例,其中此
绑定到传递给bind
的参数。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
ECMAscript 5引入了strict模式,该模式改变了函数的含义,这些函数不是作为方法调用的,也不是通过call或apply调用的,因此我们必须添加一个新规则:
7-在严格模式下,不允许此
引用全局对象(浏览器中的窗口)。因此,当函数未作为方法调用或此
未通过调用
或应用
或绑定
手动绑定到任何对象时,此
将变为未定义
:
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6引入了箭头函数。箭头函数通过提前绑定来更改其行为
8-在箭头函数中,此
在声明函数时绑定。因此,以下代码中的此
:
var x = () => {return this};
var x = function () {return this}.bind(this);
其行为与声明函数类似,如以下代码所示:
var x = () => {return this};
var x = function () {return this}.bind(this);
请注意,由于箭头函数中的此
在声明函数时已绑定,因此如果要使用继承,则不能使用箭头函数。这是因为函数中的this
将始终指向父对象,而不会指向子对象。这意味着使继承与arrow函数一起工作的唯一方法是重写所有arrow函数