1、call的实现
Function.prototype.myCall = function(context,...args){
var context = context || window;
//这里的this指的是调用 mycall 的函数
// 并为要指向的对象添加一个 fn 方法
context.fn = this;
// 并立即调用
var result = context.fn(...args);
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete context.fn;
return result;
}
2、apply的实现
- 前部分与call一样
- 第二个参数没有用扩展运算符,接收是一个数组
Function.prototype.myApply = function(context,args){
var context = context || window;
//这里的this指的是调用 myApply 的函数
// 并为要指向的对象添加一个 fn 方法
context.fn = this;
// 并立即调用
var result = context.fn(...args);
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete context.fn;
return result;
}
3、bind的实现
实现方法:
-
bind 方法不会立即执行,需要返回一个待执行的函数;(闭包)
-
实现作用域绑定(apply)
-
参数传递(apply 的数组传参)
-
当作为构造函数的时候,进行原型继承
Function.prototype.myBind = function (context, ...args) {
//新建一个变量赋值为this,表示当前函数
const fn = this
//判断有没有传参进来,若为空则赋值[]
args = args ? args : []
//返回一个newFn函数,在里面调用fn
return function newFn(...newFnArgs) {
if (this instanceof newFn) {
返回的函数当构造函数用,可以返回直接的结果
return new fn(...args, ...newFnArgs)
}
// 如果不用上面判断,此时返回的值可能字符串,但此时new + 后面的值(字符串)就不能当构造函数
return fn.apply(context, [...args,...newFnArgs])
}
}
4、new 的实现
-
当构造函数最后 return 出来的是一个和 this 无关的对象时,new 命令会直接返回这个新对象,而不是通过 new 执行步骤生成的 this 对象
-
当构造函数最后返回的不是对象,那么还是会按照 new 的实现步骤,返回新生成的对象
-
让实例可以访问到私有属性;
-
让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性;
-
构造函数返回的最后结果是引用数据类型。
function _new(ctor, ...args) {
if(typeof ctor !== 'function') {
throw 'ctor must be a function'
}
let obj = new Object();
obj.__proto__ = Object.create(ctor.prototype);
let res = ctor.apply(obj, [...args]);
let isObject = typeof res === 'object' && res !== null;
let isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
}
5、instance of 的实现
function my_instance(left, right){
if(left === null || typeof left !== 'object') {
return false
}
// 获取对象的原型,也可以使用 left.__proto__
let proto = Object.getPrototypeOf(left);
while(true) {
if(proto === null) return false;
// 一般实例对象的原型和构造函数的原型指向同一个地址
if(proto === right.prototype) return true;
// 循环找left 的原型,直到找到null 或者 是等于right 的原型
proto = Object.getPrototypeOf(proto);
}
}
6、判断数据类型
function getType(obj){
const type = typeof obj;
if(type !== 'object') {
return type;
}
return Object.prototype.toString.call(obj).replace(/^\[object (\s+)\]$/, '$1');
}