前言
本篇文章小编会分享一下call,apply,bind的具体实现方法,都是围绕this的方法,所以先提及一下this的绑定机制。
this绑定机制
this包含四种绑定机制:默认绑定、隐式绑定、显式绑定、new绑定。对于绑定优先级:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定。
默认绑定
通俗来讲就是定义变量即为默认绑定,this默认指向window,要注意的是如果用let定义则有自己的单独作用域而不是定义到了window上,以及严格模式下this默认指向的是undefined。
var num = 1;
console.log(this.num); // 1
'use strict'
var num1 = 2;
console.log(this.num); // 报错
//setTimeout的比较特殊
//严格模式和非严格模式下都是window
setTimeout(function () {
console.log(this);
});
隐式绑定
对象调用方法造成this值的绑定
var a = 2
function b() {
console.log(this.a);
}
var obj = {
a: 1,
b: b
}
obj.b();
显式绑定
call、apply、bind方法对this进行的绑定
new绑定
new绑定我们最常见的就是构造对象,new会为构造的对象内默认定义一个空的this对象
function Person(name) {
this.name = name
}
var person1 = new Person('司尘');
/* person1 = {
var this = {}
再根据构造函数往this对象中去赋值
}
*/
箭头函数
箭头函数this指向在哪里声明this函数中this就指向谁
手写call、apply、bind
其实我们从他们三者的实现很容易去理解,我们最常去实现的就是通过他们去调用对象内方法,根据这个原理我们就可以很方便的去手写实现
我们先定义一个对象供后面使用
let Person = {
name: 'jack',
say(age, sex) {
// 该this指向的是
console.log(this)
console.log(`我叫${this.name},我今年${age}岁,性别${sex}`)
}
}
let Person1 = {
name: 'rose',
}
call实现
直接上代码,解释注释都在代码之中
// 这边apply代表剩余参数
Function.prototype.myCall = function (context, ...args) {
//这里默认不传就是给window
context = context || window
//给context新增一个独一无二的属性以免覆盖原有属性
const key = Symbol()
// 这边this即为调用myCall的方法
console.log(this)
context[key] = this
//通过隐式绑定的方式调用函数
const result = context[key](...args)
//删除添加的属性
delete context[key]
//返回函数调用的返回值
return result
}
Person.say.myCall(Person1, 18, '女');
apply实现
apply实现只是传递参数与call不同实现还是一样,就不做注释了
Function.prototype.myApply = function (context, args) {
context = context || window
const key = Symbol()
context[key] = this
const result = context[key](...args)
delete context[key]
return result
}
console.log('这里是手写myappply实现');
Person.say.myApply(Person1, [19, '女'] // 我叫Tom1,我今年19岁,性别女
bind实现
bind的实现简单来讲就是返回的是一个函数而不是直接执行,同时我们也要考虑到bind返回的函数同样可以传递参数进去.
Function.prototype.myBind = function (context, ...args) {
const fn = this
return function newFn(...newFnArgs) {
return fn.apply(context, [...args,...newFnArgs])
}
}
let fn = Person.say.myBind(Person1 ,10);
fn('男'); // 我叫Tom1,我今年10岁,性别男
总结
这部分涉及到this的绑定机制较为重要,理解了这一部分后面的手写这三种方法其实都是照着模子刻
ending...