JS原生函数模拟实现new和instanceof
new的模拟实现
首先要知道new操作符,在new 一个构造函数时,发生了什么:
- 创建一个新对象
- 将这个新对象的隐式原型(__proto__)指向构造函数的原型(prototype)
- 将构造函数的属性和方法添加到这个新对象中
- 返回这个新对象
ps:如果构造函数返回的是对象或者是函数则在new运算符调用这个构造函数时返回的是对象或者函数。
代码实现如下:
1 2 3 4 5 6 7 8 9 10
| function _new(...args) { let constructor = args[0]; let obj = Object.create(constructor.prototype); let res = constructor.call(obj, ...args.slcie(1)); if((typeof res === 'object' || typeof res === 'function') && res !== null) { return res; } else { return obj; } }
|
instanceof模拟实现
L instanceof R
原理: L的__proto__是不是等于R的prototype,如果不等于就再向上L.__proto__.__proto__,一直找到要么等于R.prototype,要么__proto__指向null。
代码实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function _instanceof (L, R) { let O = R.prototype; L = L.__proto__; while(true) { if(L === null) { return false; } if(O === L) { return true; }
L = L.__proto__; } }
|
函数柯里化
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function curry(fn) { let len = fn.length; return function curryfn() { let arg = Array.from(aruments); if(arg.length < len) { return function() { return curryfn.apply(this, arg.concat(...aruments))); } } else { fn.apply(this, arg); } } } function sum(a, b, c, d) { console.log(a + b + c + d); } let currySum = curry(sum); currySum(1,2)(3)(4)
|
Object.assign()实现
参考MDN ployfill
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| if (typeof Object.assign !== 'function') { Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { 'use strict'; if (target === null || target === undefined) { throw new TypeError('Cannot convert undefined or null to object'); }
var to = Object(target);
for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index];
if (nextSource !== null && nextSource !== undefined) { for (var nextKey in nextSource) { if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); }
|