系列文章
前端八股文-类型判断
前端八股文-原型链
前端八股文-继承
new本质
说明:new操作符实际返回的是一个对象-实例对象
原理:
- 1、创建一个空对象
- 2、将对象的__proto__指向函数的原型对象
- 3、改变this指向,将this指向生成的对象
- 4、返回生成的对象
代码实现:
function copyNew(Fn) {
return function () {
let obj = {
__proto__ : Fn.prototype
}
Fn.call(obj, ...arguments)
return obj
}
}
call
说明:本质是将函数放到对象中,然后调用对象中的该函数,改变this的指向
原理:
- 1、将原函数存放到传入的上下午对象中
- 2、获取原函数传入的所有参数
- 3、上下文中存放的原函数,将参数传入并调用
- 4、将上下午中临时存放的原函数删除
- 5、返回调用原函数返回的结果
代码实现:
Function.prototype.newCall = function(context) {
if (typeof this !== 'function') {
throw new Error('not function')
}
context = context || windows;
context.fn = this;
let args = [...arguments].slice(1);
let result = context.fn(...arg);
delete context.fn
return result;
}
apply
说明:本质与call一致,区别在于参数以数组方式传入
原理:
- 1、将原函数存放到传入的上下午对象中
- 2、获取原函数传入的所有参数
- 3、判断是否存在参数,调用上下文中存放的原函数,若存在参数,结构传入
- 4、将上下午中临时存放的原函数删除
- 5、返回调用原函数返回的结果
代码实现:
Function.prototype.newApply = function(context) {
if (typeof this !== 'function') {
throw new Error('not function')
}
context = context || windows;
context.fn = this;
let result;
if(arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
delete context.fn
return result;
}
bind
说明:本质是返回一个改变了this指向的原函数
定义:
- bind方法会创建一个新函数。当这个新函数被调用时,bind的第一个参数将作为它运行时的this(该参数不能被重写), 之后的一序列参数将会在传递的实参前传入作为它的参数。
- 新函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器, 提供的this值被忽略。
原理:
- 1、将当前函数存放一份副本
- 2、获取所有传入的参数
- 3、返回一个新函数
- 4、新函数判断是否是使用了new的情况
- 5、非new情况,使用apply改变this指向,传入所有参数
- 6、new的情况,返回一个原函数的实例
- 或 使用一个中转函数继承原函数的原型,将中转函数的实例赋值给返回的函数的原型,返回函数调用时,this通过instanceof 判断中转函数的原型是否在其原型链上,则返回原函数,传入所有参数即可。外面再使用new关键字。结果同实现一
代码实现一:
Function.prototype.newBind = function(context) {
if (typeof this !== 'function') {
throw new Error('not function')
}
const _self = this;
const args = [...arguments];
return function F() {
if(this instanceof F) {
return new _self(...args, ...arguments)
} else {
return _self.apply(context||windows, [...args,...arguments])
}
}
}
代码实现二:
Function.prototype.newBind1 = function (context) {
let self = this;
let args = Array.prototype.slice.call(arguments, 1);
const cacheFn = function () {};
const newFn = function () {
const newArgs = [...args, ...arguments];
if (this instanceof cacheFn) {
return self.apply(this, newArgs)
} else {
return self.apply(context, newArgs)
}
};
cacheFn.prototype = self.prototype;
newFn.prototype = new cacheFn();
return newFn
}
instanceof
说明:原型链查找
实现:
function instanceof(left, right) {
let leftValue = left.__proto__
let rightValue = right.prototype
while (true) {
if (leftValue === null) {
return false
}
if (leftValue === rightValue) {
return true
}
leftValue = leftValue.__proto__
}
}