我希望找到一个“this”关键字的明确解释,以及如何正确使用它。
它的行为似乎很奇怪,我不完全明白为什么。
这是如何工作的,何时使用?
我希望找到一个“this”关键字的明确解释,以及如何正确使用它。
它的行为似乎很奇怪,我不完全明白为什么。
这是如何工作的,何时使用?
当前回答
“这”是关于范围的。每个函数都有自己的作用域,因为JS中的所有内容都是一个对象,所以即使是一个函数也可以使用“this”将一些值存储到自身中。OOP 101教导“这”仅适用于对象的实例。因此,每次函数执行时,该函数的新“实例”都具有“this”的新含义。
大多数人在尝试在匿名闭包函数中使用“this”时会感到困惑,例如:
(function(value) { this.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = this.value; // uh oh!! possibly undefined }); })(2);
所以这里,在each()内部,“this”不包含您期望的“value”(从this.value=value;在其上方)。因此,为了克服这个(并非双关语)问题,开发人员可以:
(function(value) { var self = this; // small change self.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = self.value; // phew!! == 2 }); })(2);
试试看;你会开始喜欢这种编程模式
其他回答
关于这一点,最详细和最全面的文章可能是以下内容:
JavaScript中“this”关键字的温和解释
这背后的想法是理解函数调用类型对设置该值具有重要意义。
当难以识别时,不要问自己:
这是从哪里来的?
但一定要问问自己:
如何调用函数?
对于箭头函数(上下文透明的特殊情况),问问自己:
在定义箭头函数的地方有什么值?
在处理这个问题时,这种心态是正确的,会让你免于头痛。
javascript中的每个执行上下文都有一个this参数,该参数由以下参数设置:
如何调用函数(包括作为对象方法、调用和应用的使用、new的使用)绑定的使用箭头函数的词汇(它们采用外部执行上下文的this)代码是严格模式还是非严格模式是否使用eval调用代码
可以使用func.all、func.apply或func.bind设置此值。
默认情况下,当在DOM元素上引发事件后调用监听器时,函数的这个值就是DOM元素,这让大多数初学者感到困惑。
jQuery使用jQuery.proxy进行更改变得很简单。
这是我见过的最好的解释:清晰地理解JavaScripts
此引用总是指(并保持)object-一个单独的对象,通常用于函数或方法,尽管它可以在全局范围请注意,当我们使用strict模式时在全局函数和匿名函数中未定义绑定到任何对象。
有四种情况可能会令人困惑:
当我们传递一个方法(使用此方法)作为参数用作回调函数时。当我们使用内部函数(闭包)时。需要注意的是,闭包不能通过使用this关键字访问外部函数的this变量,因为this变量只能由函数本身访问,而不能由内部函数访问。当依赖于此的方法被分配给跨上下文的变量时,在这种情况下,它引用了另一个对象,而不是最初预期的对象。与bind、apply和call方法一起使用时。
他给出了代码示例、解释和解决方案,我认为这很有帮助。
JavaScript中的this总是指正在执行的函数的“所有者”。
如果未定义显式所有者,则引用最顶层的所有者窗口对象。
所以如果我做了
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick=someKindOfFunction;
这将引用元素对象。但是要小心,很多人都会犯这个错误。
<element onclick=“someKindOfFunction()”>
在后一种情况下,您只是引用函数,而不是将其交给元素。因此,这将引用窗口对象。
要正确理解“这”,就必须理解上下文和范围以及它们之间的区别。
作用域:在javascript中,作用域与变量的可见性有关,作用域通过使用函数实现。(阅读有关范围的更多信息)
上下文:上下文与对象相关。它指函数所属的对象。当您使用JavaScript“this”关键字时,它指的是函数所属的对象。例如,在函数内部,当你说:“this.accoutNumber”时,你指的是属性“accoutNumber”,该属性属于该函数所属的对象。
如果对象“myObj”有一个名为“getMyName”的方法,当JavaScript关键字“this”在“getMyName”中使用时,它将引用“myObj”。如果函数“getMyName”是在全局范围内执行的,那么“this”是指窗口对象(严格模式除外)。
现在让我们看看一些示例:
<script>
console.log('What is this: '+this);
console.log(this);
</script>
在浏览器输出中运行abobve代码将:
根据窗口对象上下文中的输出,也可以看到窗口原型引用了对象。
现在让我们尝试函数内部:
<script>
function myFunc(){
console.log('What is this: '+this);
console.log(this);
}
myFunc();
</script>
输出:
输出是相同的,因为我们将“this”变量记录在全局范围中,并将其记录在函数范围中,我们没有更改上下文。在这两种情况下,上下文都是相同的,与寡妇对象相关。
现在让我们创建自己的对象。在javascript中,可以通过多种方式创建对象。
<script>
var firstName = "Nora";
var lastName = "Zaman";
var myObj = {
firstName:"Lord",
lastName:'Baron',
printNameGetContext:function(){
console.log(firstName + " "+lastName);
console.log(this.firstName +" "+this.lastName);
return this;
}
}
var context = myObj.printNameGetContext();
console.log(context);
</script>
输出:
因此,从上面的示例中,我们发现“this”关键字引用的是与myObj相关的新上下文,而myObject也具有到Object的原型链。
让我们再举一个例子:
<body>
<button class="btn">Click Me</button>
<script>
function printMe(){
//Terminal2: this function declared inside window context so this function belongs to the window object.
console.log(this);
}
document.querySelector('.btn').addEventListener('click', function(){
//Terminal1: button context, this callback function belongs to DOM element
console.log(this);
printMe();
})
</script>
</body>
输出:有道理吧?(阅读评论)
如果您无法理解上面的示例,让我们尝试使用自己的回调;
<script>
var myObj = {
firstName:"Lord",
lastName:'Baron',
printName:function(callback1, callback2){
//Attaching callback1 with this myObj context
this.callback1 = callback1;
this.callback1(this.firstName +" "+this.lastName)
//We did not attached callback2 with myObj so, it's reamin with window context by default
callback2();
/*
//test bellow codes
this.callback2 = callback2;
this.callback2();
*/
}
}
var callback2 = function (){
console.log(this);
}
myObj.printName(function(data){
console.log(data);
console.log(this);
}, callback2);
</script>
输出:
现在,让我们了解范围、自我、IIFE和THIS的行为
var color = 'red'; // property of window
var obj = {
color:'blue', // property of window
printColor: function(){ // property of obj, attached with obj
var self = this;
console.log('In printColor -- this.color: '+this.color);
console.log('In printColor -- self.color: '+self.color);
(function(){ // decleard inside of printColor but not property of object, it will executed on window context.
console.log(this)
console.log('In IIFE -- this.color: '+this.color);
console.log('In IIFE -- self.color: '+self.color);
})();
function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
console.log('nested fun -- this.color: '+this.color);
console.log('nested fun -- self.color: '+self.color);
}
nestedFunc(); // executed on window context
return nestedFunc;
}
};
obj.printColor()(); // returned function executed on window context
</script>
输出非常棒,对吧?