this的绑定规则,一句话总结:完全取决于上下文调用位置
- 默认绑定
浏览器非严格模式下,默认this绑定到window。严格模式下this绑定undefined
function foo () {
console.log(this.a)
}
var a = 2
foo() //2
foo() 是直接使用不带任何修饰参数引用进行调用的,只能使用默认绑定。
- 隐式绑定
大概就是函数被对象调用。this指针指向该对象
可以看一下下面的例子
var bj=10;
var obj={
name:"八戒",
age:500,
say:function(){
console.log(this);//就是obj这个对象
console.log(this.bj);//undefined
console.log(this.name)//八戒
function wk(){
console.log(this);//window
console.log(this.bj);//10
console.log(this.name);//这里显示的是为空,为什么是空而不是undefined,因为window对象自带有name属性
}
wk();
},
}
obj.say();
say()函数是经过obj对象调用的,但是wk()是并没有通过obj直接调用,只是自执行,这个时候,wk就是一个全局函数,因此该函数的this指向的就是window。
隐式绑定的函数可能会丢失对象
function foo(){
console.log(this.a) // "oops,global"
}
function doFoo(fn){
fn() // 调用位置,引用的是foo()本身,是一个不带任何参数调用的函数
}
var obj={
a:2,
foo:foo
}
var a="oops,global"
doFoo(obj.foo)
所以还是要看函数的调用位置
- 显式绑定
使用:functionName.call/apply (对象)
区别:(面试必问)
call和apply是一样的,他们的第一个参数是对象,直接绑定到this上。
区别在于call后面的参数是不定项的参数列表,而apply是一个数组(不是数组还会报错)
但是这依然不能解决之前丢失绑定的问题
硬绑定
可以解决这个问题
做法1:把绑定对象的语句foo.call(obj)
封装给你成一个函数f(),想要调用foo()功能则去调用f()。F()也叫包裹函数用来接收参数并返回值
做法2:创建一个可以重复使用的辅助函数
function bind (fn, obj) {
return function () {
return fn.apply(obj, arguments)
}
以上就是改变函数指针的第三种方法bind的原理,
使用:functionName.bind(对象)();
bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以。传入函数的参数和call一样是参数列表形式,可以写在第一个括号里,也可以写在第二个括号里
call和apply都是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用
- new绑定
使用new来调用一个函数,会自动执行以下操作(感觉面试也会问)
1.构建一个全新的对象
2.这个对象执行[[prototype]]连接
3.新对象会绑定函数调用的this
4.如果函数显式返回一个值,且返回的是一个对象,那么this就指向这个返回的对象。如果返回的不是一个对象,那么this依然指向实例
例子:
function foo(){
this.user = 'Lucas'
const o ={}
return o
}
const instance = new foo()
console.log(instance.user) //undefined
function foo(){
this.user = 'Lucas'
return 1
}
const instance = new foo()
console.log(instance.user) //'Lucas'
规则的优先级
new绑定>显式绑定 > 隐式绑定>默认绑定
举例子:说明这些优先级:
记住以上规则并不适用于箭头函数!!!
关于箭头函数的this请看这里!→箭头函数
书中还有一些关于this的介绍,猜想面试不会问道,就不写出了
可以看一下别人博客this指针的一些例子。。。
深入理解JS函数中this指针的指向 - 站住,别跑 - 博客园
网友评论