this的指向一直都是js中的一大难点,接下来将会从以下方面对this的指向进行总
结,包含一些面试题。
一、this的默认绑定
function foo() {
console.log(this) //window
}
foo()
function test1() {
console.log(this) //window
test2()
}
function test2() {
console.log(this) //window
test3()
}
function test3() {
console.log(this) //window
}
test1()
function foo(func) {
func()
}
var obj = {
name:"why",
bar: function() {
console.log(this) //window
}
}
foo(obj.bar)
二、隐式绑定
function foo() {
console.log(this)
}
var obj = {
name: "why",
foo: foo
}
obj.foo() //obj
function foo() {
console.log(this) //obj1
}
var obj1 = {
name: "obj1",
foo: foo
}
var obj2 = {
name: "obj2",
obj1: obj1
}
obj2.obj1.foo()
function foo() {
console.log(this) //window
}
var obj1 = {
name: "obj1",
foo: foo
}
var bar = obj1.foo
bar()
三、显示绑定:可以通过call,bind,apply
//apply,call指明绑定对象
function foo() {
console.log(this)
}
foo.call(window) //window
foo.call({name:"dl"}) //{name:dl}
foo.call(123) //Number{123}
//如果我们希望总是绑定到一个对象上,则可以使用bind
function foo() {
console.log(this) //obj
}
var obj = {
name: "Why"
}
var bar = foo.bind(obj)
bar()
四、内置函数绑定
//setTimeout
setTimeout(function() {
console.log(this) //window
}, 1000)
//点击事件触发
const app = document.querySelector("#app")
app.onclick= function() {
console.log(this) //app
}
//forEach函数
const arr = ['name','set','age']
arr.forEach(item => {
console.log(this) //window
}, {name:"ss"})
const arr = ['name', 'set', 'age']
arr.forEach(function () {
console.log(this) //{ name:"ss" }
}, {
name: "ss"
})
五、new绑定
对于构造函数来说:每一次new实例化对象都会执行以下操作
1、创建一个全新的对象
2、将全新的对象的原型指向该函数的原型对象上
3、新对象绑定this
4、将this返回
function Person(name) {
console.log(this) //Person {}
this.name = name //Person {name:"why"}
}
var p = new Person("why")
console.log(p)
六、规则优先级顺序
new > bind > 显示 > 隐式 > 默认
因为new不允许和call和bind一起使用。
七、特殊规则
//当使用显示绑定来绑定undefined或者null时,该显示绑定会自动被忽略
function foo() {
console.log(this)
}
var obj = {
name: "why"
}
foo.call(obj) //obj
foo.call(null) //window
foo.call(undefined) //window
var bar = foo.bind(null)
bar() //window
//当使用赋值时,同样也使用默认绑定规则
function foo() {
console.log(this)
}
var obj1 = {
name: "obj1",
foo: foo
}
var obj2 = {
name: "obj2"
}
obj1.foo(); //obj1
(obj2.foo = obj1.foo)() //window
//这个可以这样想:左边obj1.foo拿到的就是函数,赋值给右边还是原来的函数,所以就是函数直接执行
//ES6中的this指向
var obj = {
data:[],
getData: function() {
setTimeout(() => {
console.log(this) //obj对象
})
}
}
obj.getData()
//二
var obj = {
data:[],
getData: () => {
setTimeout(() => {
console.log(this) //window
})
}
}
obj.getData()
八、this指向面试题
var name = "window"
var person = {
name: "person",
sayName: function () {
console.log(this.name)
}
}
function sayName() {
var sss = person.sayName;
sss();
person.sayName();
(person.sayName)();
(b = person.sayName)();
}
sayName()
//输出
// window
// person
// person //这个加个括号和不加括号一样
// window
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
person1.foo4.call(person2)() //person2
person1.foo4().call(person2) //person1
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 这里的this绑定对于箭头函数来说没什么用
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 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
person1.foo2.call(person2) //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 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