千里之行,始于足下。 ——— 《老子》
全局中的this
console.log(this)
在全局状态中的this指向window。
函数中的this
function fn() {
console.log(this)
}
fn()
函数中的this,fn()实际相当于window.fn(), 所以函数里的this指向调用这个函数的对象,window。
对象中的this
let cat = {
name: '毛球',
sayName () {
console.log( 'my name is' + this.name)
}
}
cat.sayName()
方法中的this,指向调用方法的对象,所以这里的this指向cat对象。
构造函数中的this
function Fn() {
this.name = 'benjamin'
}
let fn = new Fn()
console.log(fn)
new 关键字发挥了作用,会将构造函数中的this指向创建出来的对象,所以此处之行fn方法时,this指向fn。
计时器中的this
let cat = {
name: '毛球',
sayName () {
setTimeout(function() {
console.log(this)
}, 1000)
}
}
cat.sayName()
实际打印的this实则指向window,因为setTimeout是window对象调用的。
箭头函数中的this
let cat = {
name: '毛球',
sayName () {
setTimeout(() => {
console.log(this)
}, 1000)
}
}
cat.sayName()
将定时器的普通函数改成箭头函数后,this指向cat对象,可以这样理解:
- 普通函数中的this,谁调用this就指向谁。箭头函数的this,在哪里定义,就指向哪里。
- 箭头函数外指向谁,那this就是指向谁。
- 箭头函数没有this。
call,apply,bind
call
funtion fn() {
console.log('hello world')
}
fn.call()
由此可见,call可以调用函数,call还可以改变函数中this的指向。
funtion fn() {
console.log(this.name)
}
let cat = {
name: '毛球'
}
fn.call(cat)
原本fn和cat并没有联系,但是通过call,能够将fn中的this,指向cat,上面结果打印 "毛球"。
apply
apply的使用方法和call类似,区别在于传参的方式。
fn.call(cat, '鱼', '肉')
fn.apply(cat, ['鱼', '肉'])
bind
bind传参方式和call一模一样。区别在于bind不会执行函数。
fn.call(cat, '鱼', '肉')
fn.bind(cat, '鱼', '肉') // 不会有打印结果
let fun = fn.bind(cat, '鱼', '肉')
fun() // bind调用的返回值,再去触发执行
call, apply, bind的应用-实现继承
function Animal() {
this.eat = function() {
console.log('eat something')
}
}
function Cat() {
Animal.call(this)
}
let cat = new Cat()
cat.eat()
分析:
- 小cat本没有eat方法,但是构造函数里掉用了call
- Cat构造函数里this指向小cat
- 所以Animal的this指向了小cat
- 小cat也就有eat方法了