call
手写实现:
Function.prototype.myCall = function(thisArg,...args){
if(typeof this != 'function'){
throw new TypeError('error')
}
const fn = Symbol('fn')
//如果thisArg本身就有一个方法叫做fn怎么办?那不是调用call之后,
//就会把它本身这个方法删掉了么?有的朋友会说,那起一个复杂点的函数名,
//保证其他人不会起这么少见的名称不就完了么?不行,这也不能保证万无一失。
thisArg = thisArg || window
thisArg[fn] = this
const result = thisArg[fn](...args)
delete thisArg[fn]
return result
}
apply
手写实现:
Function.prototype.myApply = function (context,args){
//Function是构造函数,Function.prototype指向该构造函数的原型对象,
//Function.prototype.myApply在该对象实例上写一个函数方法
//该函数传递两个参数:context(如果不传就是给window,也可以用es6给参数设置默认参数)
//args也要做出来
context = context || window
args = args ? args : []
const key = Symbol()
context[key] = this
//通过隐式绑定的方式调用函数
const result = context[key](...args)
//删除添加的属性
delete context[key]
//返回函数调用的返回值
return result
}
bind
手写实现:
// 定义这个方法为myBind
Function.prototype.myBind = function(thisArg) {
if (typeof this !== 'function') {
return;
}
var _self = this;
var args = Array.prototype.slice.call(arguments, 1)
var fnBound = function () {
// 检测 New
// 如果当前函数的this指向的是构造函数中的this 则判定为new 操作
var _this = this instanceof _self ? this : thisArg;
return _self.apply(_this, args.concat(Array.prototype.slice.call(arguments)));
}
// 为了完成 new操作
// 还需要做一件事情 执行原型 (思考题,为什么?)
fnBound.prototype = this.prototype;
return fnBound;
}
(思考题,为什么?)
this instanceof fBound这句话中的this,如果是在new关键字调用情况下,会指向newObj,而newObj就是fBound的实例,this instanceof fBound就是true,我们不再使用thatArg作为greeting的this,而是直接使用newObj作为greeting的this 。而当做普通函数调用的时候,this instanceof fBound就是false,greeting中的this依然指向 thatArg。
我们已经满足的区别的第一点,区别的第二点就是通过fBound.prototype = thatFunc.prototype;来实现。如果没有这句话,在new关键字调用下,newObj“继承”自Object;