this的指向
call()、apply()
call()、apply() 调用时候,修改this,只有当次调用修改,不影响函数本身this
call(obj)、apply(obj) 运行即调用
let obj1 = {
name: 'obj1',
fn() {
console.log(this.name)
}
}
let obj2 = {name: 'obj2'}
let newFn = obj1.fn
newFn.call(obj2) // obj2
newFn.apply(obj2) // obj2
obj1.fn() // obj1
newFn() // 打印为空,此时this指向window, 初始时 window.name=''
复制代码
bind()
bind(obj) 返回一个函数 需再次调用 ➡ bind(obj)()
// 接着上面代码
newFn.bind(obj2)() // obj2
复制代码
与call()、apply()的不同
let obj1 = {
name: 'obj1',
fn() {
console.log(this.name)
}
}
let obj2 = {name: 'obj2'}
let newFn = obj1.fn.bind(obj2)
newFn() // obj2
newFn.call(obj1) // obj2
复制代码
运行一次bind()后的 newFn,是一个bound function,简称绑定函数 MDN的详细说明
- TargetFunction:bind前的的函数
- BoundThis:绑定的this指向
- BoundArgs:传入的其它参数了。
当我们执行newFn时,就有点类似于TargetFunction.apply(BoundThis,BoundArgs)。
所以,当执行绑定函数时,this指向与形参在bind方法执行时已经确定了,无法改变。除非再次使用bind(obj)修改this
参数
call(this,arg1,arg2)
apply(this,[arg1,arg2])
bind(this,arg1,arg2)()
// 当this为null、undefined,this指向window
复制代码
构造器调用模式
function Dog(name, age){
// 这里的this都是指向实例
this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
var myDog = new Dog('多多', 8);
myDog.sayAge() // 8
console.log
myDog.__proto__.constructor // Dog
myDog instanceof Dog // true
// new一个函数时,同时 this 会被绑定到那个新对象上
复制代码
ES6 的箭头函数
箭头函数的 this 始终指向函数定义时的 this,而非执行时
箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined
var obj = {
name : "多多",
fn1: function () {
console.log(this.name)
},
fn2: function () {
setTimeout( () => {
this.fn1()
},100)
}
}
obj.fn2() // 多多
复制代码
使用场景
求数组中的最大和最小值 | var arr = [1, 2, 3, 89, 46]; var max = Math.max.apply(null, arr); // 89 var min = Math.min.apply(null, arr); // 1 |
将类数组转为数组 | var trueArr = Array.prototype.slice.call( arrayLike ); |
数组追加 | var arr1 = [1, 2, 3]; var arr2 = [4, 5, 6]; var total = [].push.apply(arr1, arr2); // 6 // arr1 = [1, 2, 3, 4, 5, 6] // arr2 = [4, 5, 6] |
判断变量类型 | function isArray(obj){ return Object.prototype.toString.call(obj) == '[Object Array]'; } // isArray([]) => true // isArray('yw') => false |