JS_01_this指向总结
一、背景
在大多数情况下, this都是出现在函数中。在全局作用域下,this在不同的环境有不同的指向:
- 浏览器: window(globalObject)
- Node环境: {}
这里主要讲的是在浏览器中的this指向:
结论:在js中,this指向什么, 跟函数所处的位置是没有关系的,跟函数被调用的方式是有关系
二、this绑定的四种方式
this的四个绑定法则:默认绑定、隐式绑定、显示绑定、new绑定
-
默认绑定:独立函数调用,只要是独立的调用方式,this指向都是window
-
案例一:
function foo() { console.log(this) } foo() //window案例二:
function foo1() { console.log(this) } function foo2() { console.log(this) foo1() //单独调用, } function foo3() { console.log(this) foo2() //单独调用, } foo3()//单独调用,案例三:
var obj = { name: "why", foo: function() { console.log(this) } } var bar = obj.foo bar() //单独调用 window案例四:
function foo() { function bar() { console.log(this) } return bar } var fn = foo() fn() // window
-
-
隐式绑定:通过一个对象的属性来调用的方式,例如 object.fn(), object对象会被js引擎绑定到fn函数的中this里面
案例一:
var obj = { name: "why", foo: foo } obj.foo() // obj对象案例二:
var obj = { name: "why", eating: function() { console.log(this.name + "在吃东西") }, running: function() { console.log(obj.name + "在跑步") } } obj.eating() //指向obj obj.running()//指向obj var fn = obj.eating fn() //指向window,为绑定一的默认方式案例三:
var obj1 = { name: "obj1", foo: function() { console.log(this) } } var obj2 = { name: "obj2", bar: obj1.foo } obj2.bar() // obj2 -
显示绑定:call,apply和bind的绑定,call和apply在执行函数时,是可以明确的绑定this, 这个绑定规则称之为显示绑定
//call/apply是可以指定this的绑定对象 foo.call(obj) //obj foo.apply(obj) //obj foo.apply("aaaa") //aaa // call和apply的区别是传参方式的不同 function sum(num1, num2, num3) { console.log(num1 + num2 + num3, this) } sum.call("call", 20, 30, 40) sum.apply("apply", [20, 30, 40]) //bind的绑定:默认绑定和显示绑定bind冲突: 优先级(显示绑定) var newFoo = foo.bind("aaa") newFoo() //aaa newFoo()//aaa newFoo()//aaa -
new绑定: 我们通过一个new关键字调用一个函数时(构造器), 这个时候this是在调用这个构造器时创建出来的对象,this = 创建出来的对象, 这个绑定过程就是new 绑定(都指向new的赋值的参数对象)
function Person(name, age) { this.name = name this.age = age } var p1 = new Person("why", 18) console.log(p1.name, p1.age) var p2 = new Person("kobe", 30) console.log(p2.name, p2.age)
三、一些函数的绑定
//1.setTimeout 指向window
setTimeout(function() {
console.log(this) // window
}, 2000)
// 2. 点击监听
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(this) // boxDiv
}
boxDiv.addEventListener('click', function() {
console.log(this) //window
})
// 3..数组.forEach/map/filter/find,如果没有传入参数,是指向window
var names = ["abc", "cba", "nba"]
names.forEach(function(item) {
console.log(item, this) // window
})
names.map(function(item) {
console.log(item, this) //传入了cba参数,绑定cba
}, "cba")
四、四个绑定的优先级
总:new > 显示 > 隐式 > 默认
-
默认显示的优先级最低
-
显示的优先级高于隐式优先级
function foo() { console.log(this) } var obj = { name: "obj", foo: foo.bind("aaa") } obj.foo() // aaa var bar = obj.foo bar() //aaa -
new的优先级高于显示(new不能和apply,call一起使用)
var obj = { name: "obj", foo: function() { console.log(this) } } // new的优先级高于隐式绑定 var f = new obj.foo() // foo{} //案例二: new的优先级高于bind function foo() { console.log(this) } var bar = foo.bind("aaa") var obj1 = new bar() //foo{}
五、特殊的绑定
-
忽略显示绑定:
function foo() { console.log(this) } foo.apply("abc") //abc foo.apply({}) //{} // apply/call/bind: 当传入null/undefined时, 自动将this绑定成全局对象 foo.apply(null) //window foo.apply(undefined)//window -
箭头函数
-
特点:箭头函数的this指向是上一箭头函数的上一级的对象
var foo = () => { console.log(this) //这个箭头函数的上一级是 window } foo()// window var obj = {foo: foo} obj.foo() // window foo.call("abc")// window -
应用场景案例:
var obj = { data: [], getData: function() { // 发送网络请求, 将结果放到上面data属性中 // 在箭头函数之前的解决方案 // var _this = this //this指向obj // setTimeout(function() { // var result = ["abc", "cba", "nba"] // _this.data = result //这里this的话指向window // }, 2000); // 箭头函数之后 setTimeout(() => { var result = ["abc", "cba", "nba"] this.data = result //这里的上一级指向obj }, 2000); } } obj.getData()
-

浙公网安备 33010602011771号