我希望找到一个清晰的解释,“this”关键字的作用是什么,以及如何正确使用它。
它似乎表现得很奇怪,我不完全明白为什么。
this
如何工作,应该在什么情况下使用?
我希望找到一个清晰的解释,“this”关键字的作用是什么,以及如何正确使用它。
它似乎表现得很奇怪,我不完全明白为什么。
this
如何工作,应该在什么情况下使用?
以下是关于this
的最详细和全面的文章:
this
的概念在于理解函数调用类型对设置this
值的重要性。
当你无法确定this
时,不要问自己:
this
从哪里获取?
而应该问自己:
这个函数是如何被调用的?
对于箭头函数(上下文透明的特殊情况),请问自己:
在定义箭头函数的地方,
this
的值是什么?
这种思维方式在处理this
时是正确的,可以帮助你避免头痛。
这是我见过最好的解释:深入理解 JavaScript 的 this
this 引用始终指向一个对象 - 一个单一的对象,通常在函数或方法中使用,但也可以在全局范围外使用。请注意,在使用严格模式时,在全局函数和未绑定到任何对象的匿名函数中,此时 this 将保持 undefined 的值。
以下是四种容易引起混淆的情况:
作者提供了代码示例、解释和解决方案,我认为非常有帮助。
在伪经典的术语中,许多讲座教授“this”关键字的方式是将其视为由类或对象构造函数实例化的对象。每次从类构造新对象时,可以想象在幕后创建并返回一个本地实例化的“this”对象。我记得它是这样教的:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
this
是JavaScript中一个常被误解的概念,因为它在不同的地方有些微不同的行为。简单来说,this
指的是我们当前执行的函数的“拥有者”。
this
帮助我们获取当前对象(也称为执行上下文),以便我们能够理解当前this
所指向的是哪个对象。
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
this
的地方
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
this
设置为点号前面所引用的对象。因此,在最后一行中,您可以理解a()
是在全局上下文中执行的,即window
。
this
可用于引用正在创建的对象。function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
当执行新的Person()
时,会创建一个全新的对象。调用Person
并将其this
设置为引用该新对象。
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
如果我们忘记使用new
关键字,whatIsThis
会引用它能找到的最全局的上下文(window
)
如果事件处理程序是内联的,this
指向全局对象。
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
通过JavaScript添加事件处理程序时,this
指的是生成事件的DOM元素。
.apply()
、.call()
和.bind()
来操纵上下文var that = this
的含义是什么?"this"的值取决于函数执行的上下文。上下文可以是任何对象或全局对象,即window。
因此,“this”的语义与传统的面向对象编程语言不同。这会导致问题: 1. 当一个函数被传递给另一个变量(很可能是回调)时;2. 当闭包从类的成员方法中调用时。
在这两种情况下,this被设置为window。
这个链接(http://www.quirksmode.org/js/this.html)有帮助吗?(JavaScript中“this”的大多数混淆都来自于它通常不与您的对象关联,而是与当前执行范围相关--虽然可能并不完全是这样,但对我来说总是感觉是这样--请参阅文章以获取完整解释)
关于this关键字的一些信息
让我们在全局范围内将this
关键字记录到控制台,不需要任何其他代码但是
console.log(this)
window
。console.log(this === window) // true
在 服务器/Node/Javascript 运行时 中,this
关键字也是一个全局对象,即 module.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
请记住,exports
只是对module.exports
的引用。
有不同的方式可以使用"this"关键字,以下是其示例(方法、常规函数、箭头函数、事件监听器、显式函数绑定)。
1. 在方法内部。
this ===(调用该方法的对象)。
在上面的示例中,方法“fullName()”由一个对象“person”调用,因此方法“fullName()”内部的this值将等于“person”对象。
2. 在函数内部。
i) 函数声明/表达式
注意:使用函数声明或函数表达式方法定义函数时,此属性的工作方式相同。
ii) 箭头函数:
箭头函数没有自己的 this 属性,它们将 this 的值作为其周围的函数。 如果周围的函数不存在,即它们在全局级别定义,则 this === window (对象)
3. 事件监听器 this === 附加处理程序的对象。 click事件绑定到Document对象。
在上面的例子中,由于点击处理程序附加到“document”对象,因此这将等于“document”对象。globalThis
而不是 window
。 “箭头函数没有自己的 this 属性” 是含糊的。 this
不是对象(ES 语言值)的属性,而是环境记录(ES 规范值)上的内部插槽。箭头函数不会 绑定 this
。 如果它们在全局级别定义,则相同的严格与松散模式规则适用。事件监听器实际上并不特殊;addEventListener
使用 currentTarget
属性将侦听器函数调用为 this
绑定的接收事件。 - Sebastian Simonthis
值,但是你可以创建自己的API来实现这一点。 “在上面的例子中”?该示例在下面。 - Sebastian SimonfunctionObject.call(objectForThis, arg0, arg1, arg2, ...);
“objectForThis”总是提供了某些值。
其他所有内容都是对functionObject.call
的语法糖
因此,可以通过它如何转换为functionObject.call
来描述其他所有内容。
如果只调用一个函数,则this
是“全局对象”,在浏览器中是窗口。
function foo() {
console.log(this);
}
foo(); // this is the window object
foo();
foo.call(window);
this
将为undefined
。
'use strict';
function foo() {
console.log(this);
}
foo(); // this is the window object
foo();
foo.call(undefined);
+
、-
和*
这样的运算符。还有一个点运算符.
。.
运算符实际上意味着“将对象作为this
传递给函数”。const bar = {
name: 'bar',
foo() {
console.log(this);
},
};
bar.foo(); // this is bar
bar.foo()
被翻译为const temp = bar.foo; temp.call(bar);
。const bar = {
name: 'bar',
fn1() { console.log(this); },
fn2: function() { console.log(this); },
fn3: otherFunction,
};
function otherFunction() { console.log(this) };
bar.fn1(); // this is bar
bar.fn2(); // this is bar
bar.fn3(); // this is bar
再次说,这些只是语法糖。
{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }
a.b
时,JavaScript 首先在直接由 a
引用的对象中查找属性 b
。如果在对象上没有找到 b
,则 JavaScript 将查找对象的原型以找到 b
。class
关键字。但就 this
而言,它并不重要。重要的是,在查找对象 a
的属性 b
时,如果在对象或其原型链中找到属性 b
,且 b
最终是一个函数,则应用与上述相同的规则。函数 b
引用将使用 call
方法调用,并传递 a
作为 objectForThis,如本答案顶部所示。this
并调用另一个函数的函数,然后使用 .
(点)运算符调用它。
function foo() {
console.log(this);
}
function bar() {
const objectForThis = {name: 'moo'}
foo.call(objectForThis); // explicitly passing objectForThis
}
const obj = {
bar,
};
obj.bar();
call
进行翻译后,obj.bar()
变成了const temp = obj.bar; temp.call(obj);
。当我们进入bar
函数时,我们调用foo
,但是我们明确传递了另一个对象作为objectForThis,因此当我们到达foo时,this
是那个内部对象。bind
和=>
函数的实际效果。它们更像是语法糖。它们有效地构建了一个与上面的bar
完全相同的新的不可见函数,它在调用指定的任何函数之前显式设置this
。在绑定的情况下,this
设置为您传递给bind
的内容。
function foo() {
console.log(this);
}
const bar = foo.bind({name: 'moo'});
// bind created a new invisible function that calls foo with the bound object.
bar();
// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above
bar.call({name: 'other'});
functionObject.bind
不存在,我们可以像这样自己制作一个。function bind(fn, objectForThis) {
return function(...args) {
return fn.call(objectForthis, ...args);
};
}
function foo() {
console.log(this);
}
const bar = bind(foo, {name:'abc'});
=>
运算符是绑定的语法糖。const a = () => {console.log(this)};
是同样的意思
const tempFn = function() {console.log(this)};
const a = tempFn.bind(this);
bind
类似,一个新的不可见函数被创建,它使用绑定的值来调用给定的函数,但不同于 bind
的是要绑定的对象是隐式的。它是当使用 =>
操作符时出现的 this
。const a = () => { console.log(this); } // this is the global object
'use strict';
const a = () => { console.log(this); } // this is undefined
function foo() {
return () => { console.log(this); }
}
const obj = {
foo,
};
const b = obj.foo();
b();
obj.foo()
"翻译成"const temp = obj.foo; temp.call(obj);
",这意味着foo
中的箭头运算符将会将obj
绑定到一个新的不可见函数,并返回该新的不可见函数,该函数被赋值给b
。"b()
"将像以前一样工作,即"b.call(window)
"或"b.call(undefined)
"调用foo
创建的新不可见函数。该不可见函数忽略传递给它的this
,并将obj
作为objectForThis
传递给箭头函数。
以上代码的翻译如下:
function foo() {
function tempFn() {
console.log(this);
}
return tempFn.bind(this);
}
const obj = {
foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);
functionName.apply(objectForThis, arrayOfArgs);
functionName.call(objectForThis, ...arrayOfArgs);
这个用法类似于作用域
。 <script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>
txt1和txt的值相同 在上面的例子中, $(this) = $('#tbleName tbody tr') 相同