一、this的四个绑定规则
1、默认绑定
什么情况下使用默认绑定呢?
在独立函数调用时候 独立函数调用我们可以理解成函数没有被绑定到某一个对象上进行调用
举个简单的例子`
function foo(){
console.log(this)
}
foo()//window
var obj={
name:"why",
foo:function(){
console.log(this)
}
}
var bar = obj.foo;
bar()//window
在默认绑定的情况下,this的指向是window
2、隐式绑定
比较常见的调用方式是通过某个对象进行调用的
也就是它的调用位置中,是通过某个对象发起的函数调用
function foo(){
console.log(this)
}
var obj={
name:"why",
foo:foo
}
obj.foo()//obj对象
如上图,输出的是obj2
在隐式绑定情况下,this指向的是调用的对象
3、显式绑定
如果我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,该怎么做呢?JavaScript所有的函数都可以使用call和apply方法(这个和Prototype有关)
其实非常简单,第一个参数是相同的,后面的参数,apply为数组,call为参数列表;这两个函数的第一个参数都要求是一个对象
这个对象的作用是什么呢?
就是给this准备的。在调用这个函数时,会将this绑定到这个传入的对象上。
1.call,apply
2.bind
返回的是绑定this后的新函数
function foo(){
console.log(this)
}
var newFoo=foo.bind("aaaa")
newFoo()//aaaa
4、new绑定
JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字。使用new关键字来调用函数,会执行如下的操作︰
1.创建一个全新的对象;
2.这个新对象会被执行prototype连接;
3.这个新对象会绑定到函数调用的this上 ( this的绑定在这个步骤完成)
4.如果函数没有返回其他对象,表达式会返回这个新对象;
二、其他绑定规则及绑定规则优先级
一、1.setTimeout,setInterval等全局提供的函数中,this绑定的是window
2.监听点击里面的this绑定的是这个监听点击事件的元素,boxDiv
3.另外forEach,map,filter,find方法中,都可以传第二个参数,用来绑定this的指向
4.箭头函数的this指向
箭头函数内部是不绑定this的,所有在箭头函数里面使用this,会去箭头函数上层作用域去找this
二、
1.显式绑定高于隐式绑定
2.new高于隐式
输出的是foo函数
3.new高于显式绑定
function foo() {
console.log(this)
}
var bar = foo.bind("aaa")
var obj = new bar()//foo函数
4、apply/call/bind: 当传入null/undefined时, 自动将this绑定成全局对象
function foo() {
console.log(this)
}
foo.apply("abc")
foo.apply({})
// apply/call/bind: 当传入null/undefined时, 自动将this绑定成全局对象
foo.apply(null)
foo.apply(undefined)
三、this面试题分析
1、
2、
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(); // person1(隐式绑定)
// person1.foo1.call(person2); // person2(显示绑定优先级大于隐式绑定)
// person1.foo2(); // window(不绑定作用域,上层作用域是全局)
// person1.foo2.call(person2); // window
// person1.foo3()(); // window(独立函数调用)
// person1.foo3.call(person2)(); // window(独立函数调用)
// person1.foo3().call(person2); // person2(最终调用返回函数式, 使用的是显示绑定)
// person1.foo4()(); // person1(箭头函数不绑定this, 上层作用域this是person1)
// person1.foo4.call(person2)(); // person2(上层作用域被显示的绑定了一个person2)
// person1.foo4().call(person2); // person1(上层找到person1)
3、
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) // person2(显示高于隐式绑定)
person1.foo2() // person1 (上层作用域中的this是person1)
person1.foo2.call(person2) // person1 (上层作用域中的this是person1)
person1.foo3()() // window(独立函数调用)
person1.foo3.call(person2)() // window
person1.foo3().call(person2) // person2
person1.foo4()() // person1
person1.foo4.call(person2)() // person2
person1.foo4().call(person2) // person1
var obj = {
name: "obj",
foo: function() {
}
}
4、
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()() // window
person1.obj.foo1.call(person2)() // window
person1.obj.foo1().call(person2) // person2
person1.obj.foo2()() // obj
person1.obj.foo2.call(person2)() // person2
person1.obj.foo2().call(person2) // obj
//
// 上层作用域的理解
// var obj = {
// name: "obj",
// foo: function() {
// // 上层作用域是全局
// }
// }
// function Student() {
// this.foo = function() {
// }
// }
都看到这里了,点个赞再走呗!以后还会持续更新JavaScript高级知识点的!欢迎关注!