手写代码
声明
整个知识库涉及的资料一部分为自主收集整理,一部分来源于网络收集,如有侵权请联系我
手写 new 操作符
new 操作符在 JavaScript 中用于创建一个用户定义的对象类型的实例。它的工作步骤如下:
- 首先创建了一个新的空对象
- 设置原型,将对象的原型设置为函数的
prototype
对象。 - 让函数的
this
指向这个对象,执行构造函数的代码(为这个新对象添加属性) - 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
javascript
function myNew(obj, ...args) {
// 1. 创建一个新的空对象
// 2. 将这个新对象的原型指向构造函数的 prototype 属性
const newObject = Object.create(obj.prototype)
// 3. 将构造函数内部的 this 绑定到这个新对象上,并执行构造函数的代码
const result = obj.apply(newObject, args);
// 4. 如果构造函数返回一个对象,则返回该对象;否则,返回新创建的对象
return result instanceof Object ? result : obj;
}
手写 call 函数
call 函数的实现原理步骤如下:
- 判断调用对象是否为函数,即使是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 判断传入上下文对象是否存在,如果不存在,则设置为 window。
- 处理传入的参数,截取第一个参数后的所有参数。
- 将函数作为上下文对象的一个属性。
- 使用上下文对象来调用这个方法,并保存返回结果。
- 删除刚才新增的属性。
- 返回结果。
javascript
Function.prototype.myCall = function(context) {
// 1. 判断调用对象是否为函数
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 2. 判断上下文对象是否存在,不存在则设置为window
context = context || window;
// 3. 处理传入的参数,截取第一个参数后的所有参数
const args = [...arguments].slice(1)
// 4. 将函数设为对象的属性
// 用Symbol是为了避免属性名冲突
const fn = Symbol();
context[fn] = this;
// 5. 调用函数并传入参数
const result = context[fn](...args);
// 6. 删除该属性
delete context[fn];
// 7. 返回结果
return result;
}
手写 apply 函数
apply 函数的实现原理步骤如下:
- 判断调用对象是否为函数,即使是定义在函数的原型上的,但是可能出现使用 apply 等方式调用的情况。
- 判断传入上下文对象是否存在,如果不存在,则设置为 window。
- 将函数作为上下文对象的一个属性。
- 判断参数值是否传入。
- 使用上下文对象来调用这个方法,并保存返回结果。
- 删除刚才新增的属性。
- 返回结果。
javascript
Function.prototype.myApply = function(context) {
// 1. 判断调用对象是否为函数
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 2. 判断上下文对象是否存在,不存在则设置为window
context = context || window;
// 3. 将函数设为对象的属性
// 用Symbol是为了避免属性名冲突
const fn = Symbol();
context[fn] = this;
// 4. 调用函数并传入参数
// 5. 使用上下文对象来调用这个方法
const result = arguments[1] ? context[fn](...arguments[1]) : context[fn]();
// 6. 删除该属性
delete context[fn];
// 7. 返回结果
return result;
}
手写 bind 函数
bind 函数的实现原理步骤如下:
- 判断调用对象是否为函数,即使是定义在函数的原型上的,但是可能出现使用 bind 等方式调用的情况。
- 保存当前函数的引用,获取其余传入参数值。
- 创建一个函数返回
- 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
javascript
Function.prototype.myBind = function(context) {
// 1. 判断调用对象是否为函数
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 2. 保存当前函数的引用,获取其余传入参数值
const fn = this;
const args = [...arguments].slice(1);
// 3. 创建一个返回函数
return function Fn() {
// 根据调用方式,传入不同绑定值
// 当作为构造函数使用,this指向实例,此时结果为true,将绑定函数的this指向该实例
// 当作为普通函数使用,this指向window,此时结果为false,将绑定函数的this指向context
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
}
}