前言
在项目中,this的变化让人晕头转向,但是它其实并不难,今天我们函数中this的指向,和this绑定的场景,以及绑定
this的优先级,来聊聊this的指向。
this的指向
全局函数的this指向
var a = 10
var a =function () {
console.log(this)//window
}
a()
对象方法的this指向
//对象方法里的this指当前对象
var obj = {
name: '张三',
say() {
console.log(this.name);
}
}
obj.say()//张三
事件函数里的this指向
//事件函数里的this指向触发对象
document.querySelector('button').onclick = function () {
console.log(this.name);//button
}
没有归属的匿名函数this指向
//没有归属的匿名函数this指向window
var a = 2
function fun() {
console.log(this.a);
}
var o = {
a: 3,
fun: fun
}
o.fun()//3
var p = {
a: 4
}
console.log(p.fun = o.fun);
;(p.fun = o.fun)();//2
箭头函数的this指向
//箭头函数没有自己的this,会使用外层作用域的this
console.log(this)//window
var a = 2
var test = () => {
console.log(this.a)//2
}
test()
var obj = {
a: 3,
show() {
var test = () => {
console.log(this.a);//3
}
test()
}
}
obj.show()
对象中方法的函数this指向
//对象方法中的函数this指向window
var a = 2
var obj = {
a: 3,
show() {
var test = function () {
console.log(this.a);//2
}
test()
}
}
obj.show()
显示绑定this
Function.prototype.call()
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
function foo(str1,str2){
console.log(this,str1,str2) //"aaa" 'str1' 'str2'
}
foo.call('aaa','str1','str2')
Function.prototype.apply()
apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。
function foo(str1,str2){
console.log(this,str1,str2) //"bbb" 'str1' 'str2'
}
foo.apply('bbb',['str1','str2'])
Function.prototype.bind()
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将
作为新函数的参数,供调用时使用。
function foo(str1,str2){
console.log(this,str1,str2) //'ccc','str1','str2'
}
let bar = foo.bind('ccc','str1','str2')
bar()
new的this指向
this指向实例对象
function MyClass(){
}
let myClass = new MyClass()
console.log('myClass',myClass)
绑定this的优先级(绑定this对象使用多种方式绑定)
new和默认this绑定
myClass.foo()//实例对象
结论 new的优先级高于隐式this绑定
new和call,apply
new和call、apply不能同时使用
new和bind
function foo(){
console.log(this)
}
let bar = foo.bind({name:'bar'})
let obj = {
bar
}
console.log(new obj.bar()) //空对象
bind和call和apply
bind的优先级高于call和apply
function foo(){
console.log(this)
}
let bar = foo.bind({name:'bar'})
console.log(bar.call('call'))//{name:'bar}
console.log(bar.call('apply'))//{name:'bar}
结论 new的优先级>bind的优先级>call和apply的优先级>隐式绑定的优先级>默认绑定的优先级