前端:JavaScript中的this
- 1. this的指向
- 2. 指定this的值
- 3. 手写call方法
- 4. 手写apply方法
- 5. 手写bind方法
1. this的指向
在非严格模式下,总是指向一个对象;在严格模式下可以是任意值。
开启严格模式,如果是为整个脚本开启,直接在当前脚本第一行代码写上如下代码:
'use strict'
如果是为函数开启严格模式,则是在函数第一行写上上述代码:
function a(){
'use strict'
}
- 全局执行环境中,指向全局对象即window(严格、非严格模式);
- 函数内部,取决于函数被调用的方式。如果直接调用this,严格模式下为undefined,非严格模式下为全局对象(window);如果采用对象方法调用的this, 则指向调用者(严格、非严格)
直接调用
function a(){
console.log(this);
}
function b() {
'use strict'
console.log(this);
}
a() // window
b() // undefined
对象方法调用
const food = {
name:'西瓜',
dec(){
console.log(this)
}
}
const food2 = {
name: '香蕉',
dec() {
'use strict'
console.log(this)
}
}
food.dec() // food这个对象
food2.dec() // food2这个对象
2. 指定this的值
- 调用时指定,call、apply(数组传递参数)
- 创建时指定,bind,箭头函数
call使用如下:
func.call(thisArg,参数1,参数2...)
function func(num1,num2){
console.log(this);
console.log(num1,num2);
}
const person = {
name:'baidu'
}
func.call(person,1,2)
apply使用如下:
func.apply(thisArg,[参数1,参数2...])
function func(num1,num2){
console.log(this);
console.log(num1,num2);
}
const person = {
name:'baidu'
}
func.apply(person,[2,3])
bind使用如下:
func.bind(thisArg,绑定参数1,绑定参数2...)
function func(num1,num2){
console.log(this);
console.log(num1,num2);
}
const person = {
name:'baidu'
}
const bindFunc = func.bind(person,77)
bindFunc(88)
箭头函数
使用普通函数,此时最里层的this指向window
const person = {
name:'baidu',
hh(){
console.log(this);
setTimeout(function(){
console.log(this);
},1000)
}
}
person.hh()
使用箭头函数,最里层的this指向其外层的this值。
const person = {
name:'baidu',
hh(){
console.log(this);
setTimeout(()=>{
console.log(this);
},1000)
}
}
person.hh()
3. 手写call方法
任何定义的函数都是属于Function类型,那么只需要在Function其原型上添加一个call方法,其他自定义的函数上均可以使用call方法,这里定义的call方法名为myCall。
Function.prototype.myCall = function(thisArg,...args){
thisArg.f = this
// this指向调用myCall的那个函数
const res = thisArg.f(...args)
// 传递进来的args参数为数组类型
delete thisArg.f
return res
}
但是上述还存在一个问题,那就是如果thisArgs这个对象上也刚好存在f属性,上述操作会把原对象thisArgs的f属性去掉。因此可以考虑使用Symbol,Symbol无论调用多少次,其返回值均是唯一的。
function func(num1, num2) {
console.log(this);
console.log(num1, num2);
}
const person = {
name: 'baidu'
}
Function.prototype.myCall = function(thisArg,...args){
const key = Symbol('key');
thisArg[key] = this
// this指向调用myCall的那个函数
const res = thisArg[key](...args)
delete thisArg[key]
return res
}
func.myCall(person,22,33)
运行结果:
4. 手写apply方法
和myCall类似,只是传递参数不同而已。
function func(num1, num2) {
console.log(this);
console.log(num1, num2);
}
const person = {
name: 'baidu'
}
Function.prototype.myApply = function(thisArgs,args){
const key = Symbol('key')
thisArgs[key] = this
const res = thisArgs[key](...args)
delete thisArgs[key]
return res
}
func.myApply(person,[44,66])
5. 手写bind方法
function func(num1, num2) {
console.log(this);
console.log(num1, num2);
}
const person = {
name: 'baidu'
}
Function.prototype.myBind = function(thisArgs,...args){
return (...newArgs)=>{
return this.call(thisArgs,...args,...newArgs)
}
}
const myBindFunc = func.myBind(person,1)
myBindFunc(2)
箭头函数中this指向func,即其调用者(外层this的指向)