This的设计
Javascript 是允许在函数体内引用当前环境的其他变量,因此函数可以在不同的运行环境执行,所以我们就需要一种机制,能够在函数内获得当前运行环境,由此诞生了 this ,它的设计目的就是指向函数运行时所在的环境。
如何判断This指向
1.默认绑定
严格模式:
(() => {
"use strict"
function foo() {
console.log(this.name);
};
var name = "keys";
foo(); })();
// Uncaught TypeError TypeError: Cannot read properties of undefined (reading 'name')
// at foo (d:\web\index.html:16:26)
// at <anonymous> (d:\web\index.html:19:5)
// at <anonymous> (d:\web\index.html:19:14)
在严格模式下This不会绑定为默认绑定到Window上,而是会默认绑定为undefined,从而无法访问到name。
function foo() {
console.log(this.name);
};
var name = "keys";
(() => {
"use strict"
foo(); }
)();
//keys
但是在严格模式下调用函数则不会影响默认绑定。
非严格模式
This默认绑定到全局对象
var name = 'keys'
function foo(){
console.log(this.name);//keys
console.log(this);//Window
console.log(window);//Window
}
foo();
2.隐式绑定
对象方法:通过对象属性执行函数时,此时隐式绑定规则会将 this 绑定到对象上;
一层作用域时:this指的是该对象
var name = 'keys';
function foo() {
console.log(this.name);
}
var obj = {
name: 'objkeys',
foo
}
obj.foo(); //objkeys
foo();//keys
obj.foo()是由对象obj调用的所以this隐式绑定到obj上,所以第一次输出objkeys. foo()是在全局上调用的所以,this绑定到全局对象Window上,输出keys。
多层作用域链时,this指的是距离方法最近的一层对象
var name = 'keys';
function foo() {
console.log(this.name);
}
var obj = {
name: 'objkeys',
obj1:{
name:'obj1keys',
foo
}
}
obj.obj1.foo(); //obj1keys
因为foo在对象obj,obj1中,所以this默认绑定到最近的对象obj1中,所以属性name为obj1keys。
特别地:
var name = 'keys';
var obj = {
name: 'objkeys',
obj1:{
name:'obj1keys',
foo: function(){
console.log(this.name
}
}
}
obj.obj1.foo(); //obj1keys
var obj2 = obj.obj1.foo;
obj2();//keys
通过赋值将对象里的方法给了obj2,并未真正执行当前函数,而后在全局环境下执行函数,所以this指向全局对象Window,输出keys。
3.显示绑定
通过call、bind、apply
call:使用一个指定的 this 和若干个指定的参数调用某个函数或方法.
如果call、apple、bind的绑定对象是null或者undefined,那么实际上在调用时这些值都会被忽略,所以使用的是默认绑定规则,默认绑定到Window。
function foo() {
console.log(this.name);
}
var obj = { name: 'objkeys',}
var obj1 = { name: 'objkeys1'}
var name = 'keys';
foo.call(obj); // objkeys
foo.call()//keys
4.构造函数的调用,this指的是实例化的新对象
var name = 'keys';
function Foo(){
this.name = 'keys1';
this.type = 'type';
}
var foo = new Foo();
console.log(foo.name);//keys1
5.匿名函数
this指向的是全局对象window
var name = 'keys';
var obj = {
name:'objkeys',
foo:(function(){
console.log(this.name);
})()
}
obj.foo;//keys
6.箭头函数
ES6新增了一种函数类型:箭头函数,它和普通函数最不同的一点就是对于箭头函数的 this 指向,是根据它外层(函数/全局)作用域来决定。因为其本身没有this所以会按照外层作用域来执行。this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象。
var name = 'window';
var obj = {
name: 'objkey',
Foo: function(){
// var self = this;
var foo = () => {
// console.log(self.name);
console.log(this.name);
}
foo();
},
Foo1: () => {
console.log(this.name);
},
Foo2:function(){
console.log(this.name);
}
}
obj.Foo(); // 'objkey'
obj.Foo1();// 'window'
obj.Foo2(); // 'objkey'
7.规则优先级
1、new绑定var obj = new Foo();this绑定新的对象上
2、显示绑定var obj = foo.call(bar);this绑定到指定对象上,若指定对象为null/undefined或着没传,则使用默认绑定规则
3、隐式绑定
var obj = bar.foo();this绑定到调用方法的对象上
4、默认绑定foo();this在严格模式下绑定到undefined
8.DOM事件处理函数中this的指向
<button class="button">onclick</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var button = document.querySelector('button');
button.onclick = function(e){
console.log(this);
console.log(this === e.currentTarget); // true
}
var list = document.querySelector('.list');
list.addEventListener('click', function(e){
console.log(this === list); // true
console.log(this === e.currentTarget); // true
console.log(this);
console.log(e.target);
}, false);
</script>
小结
1.普通函数的调用,this指向的是window
2.对象方法的调用,this指的是该对象,且是最近的对象
3.显示绑定call调用,this指向参数中的对象
4.构造函数的调用,this指的是实例化的新对象
5.匿名函数的调用,this指向的是全局对象window,定时器相当于匿名函数
6.箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象
7.new>显示>隐式>默认
8.onclick和addEventerListener是指向绑定事件的元素
参考网址:
https://blog.csdn.net/weixin_30980795/article/details/107448842
https://baijiahao.baidu.com/s?id=1763115725232602497&wfr=spid...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。