call方法的實(shí)現(xiàn)
Function.prototype.myCall = function (context) {
//this 調(diào)用的函數(shù)
//context 調(diào)用函數(shù)的對(duì)像
// 判斷this是否為函數(shù)
if (typeof this !== 'function') {
throw TypeError('Error')
}
context = context || window
//聲明一個(gè)Symbol 防止fn被占用
const fn = Symbol('fn')
//將函數(shù)添加成為contxt 對(duì)象的方法被調(diào)用
context[fn] = this
//獲取參數(shù)
//const args = Array.prototype.slice.call(arguments, 1)
//const args = Array.from(arguments).slice(1)
const args = [...arguments].slice(1)
//調(diào)用返回結(jié)果
const result = context[fn](...args)
//刪除方法
delete context[fn]
//返回結(jié)果
return result
}
apply方法實(shí)現(xiàn)
Function.prototype.myApply = function (context){
if (typeof this !== 'function') {
throw TypeError('Error')
}
context = context || window
const args = arguments[1]
const fn = Symbol('fn')
context[fn] = this
const result = context[fn](...args)
delete context[fn]
return result
}
bind方法實(shí)現(xiàn)
Function.prototype.myBind = function (context){
if (typeof this !== 'function') {
throw TypeError('Error')
}
const args = [...arguments].slice(1)
let _this = this
return function F(){
if (this instanceof F) {
return new _this(...args, ...arguments)
} else {
return _this.call(context, ...args, ...arguments)
}
}
}
//例題
function print(age) {
console.log(this.name+ "" + age)
}
let obj = {
name: "李華"
}
print.myCall(obj,1,2,3) //李華1
print.myApply(obj,[3,2,1]) //李華3
new方法實(shí)現(xiàn)
function myNew(){
//創(chuàng)建一個(gè)新對(duì)象
let obj = new Object()
//獲取到構(gòu)造函數(shù)
let Constructor = Array.prototype.shift.call(arguments)
//將對(duì)象的__proto__(隱形原型屬性) == 構(gòu)造函數(shù)的 prototype 顯示原型屬性
obj.__proto__ = Constructor.prototype
//將構(gòu)造函數(shù)作為對(duì)象的方法被調(diào)用
let ret = Constructor.apply(obj, arguments)
// 如果構(gòu)造函數(shù)返回值是對(duì)象則返回這個(gè)對(duì)象爆侣,如果不是對(duì)象則返回新的實(shí)例對(duì)象
return typeof ret === "object" && ret !== null ? ret : obj
}
//例題:
// ========= 無(wú)返回值 =============
// const testNewFun = function(name) {
// this.name = name;
// };
//
// const newObj = myNew(testNewFun, 'foo');
//
// console.log(newObj); // { name: "foo" }
// console.log(newObj instanceof testNewFun); // true
// ========= 有返回值 =============
const testNewFun = function(name) {
this.name = name;
return {};
};
const newObj = myNew(testNewFun, 'foo');
console.log(newObj); // {}
console.log(newObj instanceof testNewFun); // false
reduce實(shí)現(xiàn)
Array.prototype.myReduce = function (callbackFn){
let o = this
let k = 0,
kPresent = false,
accumulator,
initialValue = arguments.length > 0 ? arguments[1] : undefined,
len = this.length
if (typeof callbackFn !== 'function') {
throw TypeError('Error')
}
if (len === 0 && initialValue !== undefined) {
throw TypeError('Error')
}
if (initialValue !== undefined) {
accumulator = initialValue
} else {
accumulator = o[k]
++k
}
while (k < len) {
kPresent = o.hasOwnProperty(k)
if (kPresent) {
accumulator = callbackFn.apply(undefined, [accumulator, o[k], k, o])
}
++k
}
return accumulator
}
const rReduce = ['1', null, undefined, , 3, 4].reduce((a, b) => a + b, 3);
const mReduce = ['1', null, undefined, , 3, 4].myReduce((a, b) => a + b, 3);
console.log(rReduce, mReduce)