我希望找到一个“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);
试试看;你会开始喜欢这种编程模式
其他回答
作用域的用法如下
<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')相同
JavaScript中的this总是指正在执行的函数的“所有者”。
如果未定义显式所有者,则引用最顶层的所有者窗口对象。
所以如果我做了
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick=someKindOfFunction;
这将引用元素对象。但是要小心,很多人都会犯这个错误。
<element onclick=“someKindOfFunction()”>
在后一种情况下,您只是引用函数,而不是将其交给元素。因此,这将引用窗口对象。
“this”的值取决于执行函数的“上下文”。上下文可以是任何对象或全局对象,即窗口。
因此,“this”的语义不同于传统的OOP语言。这会导致问题:1.当一个函数传递给另一个变量时(很可能是回调);和2。当从类的成员方法调用闭包时。
在这两种情况下,这都设置为window。
关于此关键字的一些信息
让我们将此关键字记录到全局范围内的控制台中,无需任何代码
console.log(this)
在客户端/浏览器中,此关键字是一个全局对象,它是窗口
console.log(this === window) // true
and
在Server/Node/Javascript运行时中,此关键字也是一个全局对象,即module.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
请记住,导出只是对module.exports的引用
我对这个问题的看法与我希望有帮助的其他答案不同。
查看JavaScript的一种方法是看到只有一种方法可以调用函数1。它是
functionObject.call(objectForThis, arg0, arg1, arg2, ...);
始终为objectForThis提供一些值。
其他一切都是functionObject.call的语法糖
因此,其他一切都可以通过它如何转换为functionObject.call来描述。
如果你只是调用一个函数,那么这就是“全局对象”,在浏览器中就是窗口
函数foo(){console.log(此);}foo();//这是窗口对象
换句话说,
foo();
被有效地转化为
foo.call(window);
请注意,如果使用严格模式,则这将是未定义的
“使用严格”;函数foo(){console.log(此);}foo();//这是窗口对象
这意味着
换句话说,
foo();
被有效地转化为
foo.call(undefined);
在JavaScript中有+、-和*等运算符。还有点运算符。
这个运算符与右侧的函数和左侧的对象一起使用时,实际上意味着“将对象作为this传递给函数”。
实例
常量bar={name:'bar',foo(){console.log(此);},};bar.foo();//这是酒吧
换句话说,bar.foo()转换为consttemp=bar.foo;临时呼叫(bar);
注意,函数的创建方式并不重要(主要是…)。所有这些都会产生相同的结果
常量bar={name:'bar',fn1(){console.log(this);},fn2:function(){console.log(this);},fn3:其他函数,};函数otherFunction(){console.log(this)};bar.fn1();//这是酒吧bar.fn2();//这是酒吧bar.fn3();//这是酒吧
同样,这些都只是语法糖
{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }
另一个褶皱是原型链。当您使用.b时,JavaScript首先查找属性b的a直接引用的对象。如果在对象上找不到b,则JavaScript将在对象的原型中查找b。
定义对象原型的方法多种多样,2019年最常见的是class关键字。出于这个目的,尽管这并不重要。重要的是,当它在对象a中查找属性b时,如果它在对象上找到属性b,或者在它的原型链中找到属性b(如果b最终是一个函数),那么上述规则同样适用。函数b引用将使用call方法调用,并将a作为objectForThis传递,如该答案顶部所示。
现在让我们想象一下,在调用另一个函数之前,我们创建了一个显式设置此值的函数,然后使用调用它。(点)运算符
函数foo(){console.log(此);}函数栏(){const objectForThis={name:“moo”}foo.call(objectForThis);//显式传递objectForThis}常量对象={酒吧};obj.bar();
在转换为使用调用之后,obj.bar()变为consttemp=obj.bar;临时调用(obj);。当我们进入bar函数时,我们调用foo,但我们显式地为objectForThis传递了另一个对象,所以当我们到达foo时,这是内部对象。
这是bind和=>函数有效的作用。它们是语法糖。他们有效地构建了一个新的不可见函数,就像上面的bar一样,它在调用指定的函数之前显式地设置了这个函数。在绑定的情况下,这将设置为传递给绑定的任何值。
函数foo(){console.log(此);}const bar=foo.bind({name:“moo”});//bind创建了一个新的不可见函数,该函数使用绑定对象调用foo。bar();//我们在这里传递给bar的objectForThis被忽略,因为//绑定创建的不可见函数将使用//我们在上面绑定的对象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一样,会创建一个新的不可见函数,该函数使用objectForThis的绑定值调用给定函数,但与bind不同的是,要绑定的对象是隐式的。当使用=>运算符时,这就是发生的情况。
所以,就像上面的规则一样
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()转换为consttemp=obj.foo;临时调用(obj);这意味着foo中的箭头运算符将obj绑定到一个新的不可见函数,并返回分配给b.b()的新的不可视函数。该不可见函数忽略传递给它的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);
1apply是另一个类似于调用的函数
functionName.apply(objectForThis, arrayOfArgs);
但从概念上讲,ES6甚至可以将其转换为
functionName.call(objectForThis, ...arrayOfArgs);