前言
很多刚入门的小伙伴可能搞不懂this
指向,很多时候就是硬凑,这个不对换一种写法,再不对再换一种,直到找到自己的目标this
,反正能跑一个就行嘛。但是很多时候面试必不可少的会问到这些,而且如果开始时不注意会多写很多不必要的代码,可读性不强,今天我们就来看下this
指向到底指的啥!
this 绑定规则
首先我们可以将this绑定大致分为以下几类:
默认绑定
独立函数调用时使用默认绑定,独立函数调用可以理解成函数没有被绑定到某个对象上进行调用
// 1. 普通函数独立调用
function foo(){
console.log(this)
}
foo() // Window对象,严格模式时为undefined
// 2. 函数定义在对象中,赋值给一个变量独立调用
let obj={
name:'xxx',
bar:function(){
console.log(`bar-this`, this);
}
}
let foo1=obj.bar
foo1() // Window对象,严格模式时为undefined
再举个例子,
// 3. 高阶函数
let obj={
name:'xxx',
bar:function(){
console.log(`bar-this`, this);
}
}
function foo2(fn){
fn()
}
foo2(obj.bar) // Window对象,严格模式时为undefined
由此看出this
的绑定和编写的位置没有关系,它和调用方式以及位置有关
注:严格模式下独立调用函数中的this
指向的是undefined
显式绑定
通过call
或者apply
或者bind
方法
函数.call(对象,xx)
函数.apply(对象,[xx])
// 传入的这个对象会和this绑定上
// 后面的参数,call为参数列表,apply为数组
例如:
function foo(){
console.log(this);
}
let obj = {
name:'xx1'
}
foo.call(obj) // obj对象
foo.apply(obj) // obj对象
隐式绑定
通过某个对象进行绑定,换句话说就是通过某个对象发起的函数调用。下面举几个案例
function foo(){
console.log(`foo-this`,this);
}
let obj = {
name:'xxx',
bar:foo
}
obj.bar() //obj对象
function foo(){
console.log(`foo-this`,this);
}
let obj1 = {
name:'xxx1',
foo1:foo
}
let obj2 = {
name:'xxx2',
foo2:obj1
}
obj2.foo2.foo1() // obj1对象
new绑定
function Foo() {
console.log(this);
}
new Foo() // Foo的实例对象
另外回顾下new
做了哪些事
- 创建一个新的空对象
- 将this指向这个空对象
- 执行代码
- 没有显式返回非空对象时,默认返回此对象
一些内置函数
在此简单举例
- 计时器
setTimeout(function(){
console.log(this); // Window对象
},500)
- forEach
const filmList = ["xx1", "xx2", "xx3"]
filmList.forEach(item=>{
console.log(this); // Window对象
})
规则优先级
上面我们说的都是分类的独立调用,那多个的呢?如果应用类多条规则那优先级哪个更高些呢?
- 默认绑定优先级最低
- 显式绑定高于隐式绑定
new
绑定高于隐式绑定new
不会和apply
/call
一起使用new
绑定高于bind
绑定bind
高于apply
/call
特殊
显示绑定null
或undefined
function foo() {
console.log(this);
}
foo.apply(null) // Window对象 严格模式下为null
foo.apply(undefined) // Window对象 严格模式下为undefined
foo.call(undefined) // Window对象 严格模式下为undefined
间接函数引用
let obj1 = {
name: 'xx1',
foo: function(){
console.log(this);
}
}
let obj2 = { name: 'xx2' };
(obj2.foo = obj1.foo)() // Window对象(会被当作独立函数调用)
箭头函数
写法:
let foo = (参1,参2) => {}
- 箭头函数不会绑定
this
arguments
- 箭头函数不能作为构造函数使用
箭头函数中没有this,如果在其中使用this
,它会往它的上层作用域查找对应的this
举例:
// 一
let foo = () => {
console.log(`foo-this`, this);
}
foo() // Window对象
foo.apply("xxx") // Window对象
// 二
let obj = {
name: 'xx1',
foo: function() {
let bar = () =>{
console.log(`bar-this`, this);
}
return bar
}
}
let fn = obj.foo()
fn() // obj对象
fn.apply('xxx2') // obj对象
// 三,变形一下
let obj = {
name: 'xx1',
foo: () => {
let bar = () =>{
console.log(`bar-this`, this);
}
return bar
}
}
let fn = obj.foo()
fn() // Window对象
fn.apply('xxx2') // Window对象
好了,以上就是this
指向相关的内容,如果大家有不同意见可以在下方评论,一起探讨下✌️