简介

bind 实现学习笔记。

call 实现

Function.prototype.fakeCall = function(context, ...args) {
    // 传入 null 和 undefined均 指向 window
    context = context || window;
    context.fn = this;

    let result = context.fn(...args);
    delete context.fn;

    return result;
}

const bar = function(name, age) {
    return  {name, age};
};
const obj = { value: 1 };

// 1、传入null
console.log(bar.fakeCall(null));
// 2、有返回值
console.log(bar.fakeCall(obj, 'kevin', 18));

apply 实现

Function.prototype.fakeApply = function (context, arr) {
    // 传入 null 和 undefined均 指向 window
    context = context || window;
    context.fn = this;

    result = context.fn(...arr);
    delete context.fn;

    return result;
}

const bar = function(name, age) {
    return  {name, age};
};
const obj = { value: 1 };

// 1、传入null
console.log(bar.fakeApply(null));
// 2、有返回值
console.log(bar.fakeApply(obj, ['kevin', 18]));

bind 实现

Function.prototype.fakeBind = function(context, ...args) {
    if (typeof this !== 'function') {  
        throw new Error('when use bind, it must be a function');
    }

    let self = this;

    let resultFuc = function(...args2) {
        const current = this instanceof self ? this : context;
        self.apply(current, args.concat(args2));
    }

    // resultFuc.prototype 的原型是 self.prototype
    // 即 resultFuc 原型的原型是 self.prototype
    resultFuc.prototype = Object.create(self.prototype);
    return resultFuc;
}

let foo = { value: 1 };
function bar(name, age) {
    console.log(this);
    console.log(this.value);
    this.name = name;
    this.age = age;
}
bar.prototype.friend = 'friend';

// 1、普通函数: foo
let bind1 = bar.fakeBind(foo, 'name1');
let obj1 = bind1(10);

// 2、构造函数: new bar
let bind2 = bar.fakeBind(foo, 'daisy');
let obj2 = new bind2('name2');
console.log(obj2.__proto__.__proto__ === bar.prototype);

应用

call 函数示例

let arr = [' ab', ' c d'];
console.log(arr.map(Function.prototype.call, String.prototype.trim));

// 1、map 方法第二个参数作用是用来定义执行 callback 时的 this 指向
var arr = [' ab', ' c d'];
var obj = { 'test': 'test' }
arr.map(function(item) {
    // obj
    console.log(this);
}, obj);

//  2、以遍历到第一个元素为例
Function.prototype.call.call(String.prototype.trim, ' ab');
// 等价于
String.prototype.trim.call(' ab');
// 等价于
' ab'.trim();

bind 函数示例一

let bindf = Function.prototype.call.bind(Array.prototype.slice);
bindf([1, 2, 3]);

// 等价于
Function.prototype.call.apply(Array.prototype.slice, [1, 2, 3])
// 等价于
Array.prototype.slice.call([1, 2, 3])
// 等价于
[1, 2, 3].slice()

bind 函数示例二

let x = 10;
let y = function() {
    console.log(this.x);
};
let obj1 = { x: 100 };
let obj2 = { x: 2 };
let obj3 = { x: 3 };
func = y.bind(obj1).bind(obj2).bind(obj3);
func();
// 等价于
(y.bind(obj1).bind(obj2)).apply(obj3);

// 等价于 obj3 执行下面函数
y.bind(obj1).bind(obj2)

// 等价于 obj2 执行下面函数 
y.bind(obj1)

// 等价于 obj1 执行下面函数 
y
powered by Gitbook该文件修订时间: 2023-05-16 18:08:03

results matching ""

    No results matching ""