JS原理中this的绑定

78 阅读2分钟

this四大绑定

  • 默认绑定
function foo(){
	console.log(this)
}
foo() //输出windows
  • 隐式绑定
var obj={
	name:"obj",
	foo:function(){
		console.log(this.name)
	}
}
obj.foo() //输出obj
  • 显示绑定
//call apply bind
function foo(){
	console.log(this)
}
foo.call("abc") //输出"abc"

  • new绑定
function foo(a) {
    this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2

优先级顺序:new绑定>显示绑定(apply/call/bind)>隐式绑定(obj.foo()) >默认绑定

  • 忽略显示绑定
funciton foo(){
	console.log("foo")
}
foo.apply(null) //指向windows
foo.call(undefined) //指向windows

  • 箭头函数的this获取 寻找上层作用域 显示绑定不生效
var name = "window"

function Person(name){
	this.name = name;
	this.foo2 = function(){
		return ()=>{
			console.log(this.name) //this.name指向的是foo2的作用域的this
		}
	}
}

var person1 = new Person("person1")
var person2 = new Person("person2")

person1.foo2()() //person1
person1.foo2.call(person2)()//person2 作用域已更改为person2

this绑定的分析图

🚧🚧:分析几道面试题

题目来源:juejin.cn/post/684490…

  • 字面量对象
var name = 'window'
var person1 = {
  name: 'person1',
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person2 = { name: 'person2' }

person1.foo1()//foo1被person1显式调用,输出person1
person1.foo1.call(person2)//foo1被persopn2改变this指向,输出person2

person1.foo2()//箭头函数看上层作用域,为全局作用域,输出window
person1.foo2.call(person2)//call函数无效,输出window

person1.foo3()()//person1.foo3()得到内部function,之后被全局调用,输出window
person1.foo3.call(person2)()//改变foo3的this不影响被全局调用,输出window
person1.foo3().call(person2)//内部funciton被person2对象call调用,输出person2

person1.foo4()()//箭头函数看上层作用域,即foo4函数,foo4被person1调用,输出person1
person1.foo4.call(person2)()//foo4函数被call改变指向,输出person2
person1.foo4().call(person2)//还是看上层作用域foo4,输出persopn1
  • 构造函数
var name = 'window'
function Person (name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.foo1()//显示绑定,输出person1
person1.foo1.call(person2)//被call调用,输出person2

person1.foo2()//箭头函数看上层作用域,为person1,输出person1
person1.foo2.call(person2)//call不改变作用域,输出person1

person1.foo3()()//person1.foo3()得到内部function,进行全局调用,输出window
person1.foo3.call(person2)()//同上全局调用,输出window
person1.foo3().call(person2)//得到内部function后被call调用,输出person2

person1.foo4()()//箭头函数看上层作用域,为foo4函数被person1调用,输出person1
person1.foo4.call(person2)()//foo4函数被call指向person2,输出person2
person1.foo4().call(person2)//此时call不影响foo4的作用域,输出person1
  • 构造函数2
var name = 'window'
function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    foo1: function () {
      return function () {
        console.log(this.name)
      }
    },
    foo2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.obj.foo1()()//person1.obj.foo1()得到内部function,被window调用,输出window
person1.obj.foo1.call(person2)()//foo1被call改变指向了,但是内部function还是被window调用,输出window
person1.obj.foo1().call(person2)//得到内部funtion后call调用,指向person2,输出person2

person1.obj.foo2()()//箭头函数看上层作用域foo2,foo2被obj调用,输出obj
person1.obj.foo2.call(person2)()//foo2被call改变指向了,输出person2
person1.obj.foo2().call(person2)//没有改变foo2的指向,依然输出obj

🚀🚀总结:this永远指向最后调用它的那个对象!!!