# this
# this 的确定
this 的指向在函数执行的时候确定,不是在定义的时候确定的。
- 作为普通函数: window
- 使用 call apply bind:传入什么就绑定什么
- 作为对象方法被调用:对象本身
- 在 class 方法中调用:this 就是实例对象
- 箭头函数:取决于上层作用域的this
这里需要注意的是 setTimeout 中 this 的指向,如果是普通函数,就是 Windows,如果是箭头函数就是他的取决于上层作用域的this
function fn1() {
console.log(this)
}
fn1() // window
// call 直接调用执行
fn1.call({ x: 100 }) // { x: 100 }
// bind 会返回一个新的函数去执行
const fn2 = fn1.bind({ x: 200 })
fn2() // { x: 200 }
const zhangsan = {
name: 'zhangsan',
sayHi() {
// this 即当前对象
console.log(this)
},
wait() {
// setTimeout 触发的执行不是对象的方法执行
setTimeout(function() {
// this === window
console.log(this)
})
}
}
// 箭头函数的this是取决于上层作用域的this
const lisi = {
name: 'lisi',
sayHi() {
// this 即当前对象
console.log(this)
},
wait() {
setTimeout(() => {
// this 即当前对象
console.log(this)
})
}
}
class People {
constructor(name) {
this.name = name
this.age = 20
}
sayHi() {
console.log(this)
}
}
const wangwu = new People('wangwu')
wangwu.sayHi() // wangwu 对象
# 手写 bind 函数
// 模拟 bind
Function.prototype.bind1 = function() {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取 this(数组第一项)
const t = args.shift()
// fn1.bind(...)中的 fn1
const self = this
// 返回一个函数
return function() {
return self.apply(t, args)
}
}
// 手写 bind 函数
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
const fn2 = fn1.bind1({ x: 100 }, 10, 20, 30)
const res = fn2()
console.log(res)
# 实例:创建 10 个 a 标签,点击的时候弹出来对应的序号
for (let i = 0; i < 10; i++) {
let a
a = document.createElement('a')
a.innerHTML = i + '<br/>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
# this 指向
class Person {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat something`)
}
}
// 子类
class Student extends Person {
constructor(name, number) {
super(name)
this.number = number
}
sayHi() {
console.log(this.name, this.number)
}
}
const jie = new Student('jie', 123)
console.log(jie.name) // 'jie'
console.log(jie.__proto__.name) // undefined
// 因为 jie.__proto__.name 的调用 jie.__proto__ 对象没有 name 属性。他的 this 指向的是 jie.__proto__
# new 操作符
new 操作符调用构造函数具体做了有以下:
- 创建一个新的对象
- 将构造函数的 this 指向这个新的对象
- 为这个对象添加属性、方法等
- 最终返回新的对象
一般使用 new 方法调用构造函数时,构造函数体内的 this 会绑定到新创建的对象上;这里需要注意的是,如果构造函数中显式返回一个值,且返回的是一个对象(返回复杂类型),那么 this 就指向这个返回的对象;如果返回的不是一个对象(返回的是基本类型),那么 this 仍然指向实例。
# this 优先级
显式绑定 this 有:call、apply、bind、new 等操作。对于这些操作符的优先级,new 绑定的优先级比其他显式绑定方法更高;
箭头函数时不能修改其绑定值的。如何区分 new 或者其他显式绑定这两种,可以通过 instanceof 来进行判断
# let、const
这里有个小知识点,使用 let、const 声明的变量不会挂在到 window 全局对象上。 还有一个小细节,函数的 length 属性,用来表示形参的个数。
阅读量:
评 论:
← class、原型与原型链 同步跟异步 →