Будет ли это приемлемым решением для Polyfill для JavaScript метода связывания? - PullRequest
1 голос
/ 17 февраля 2020

Сначала я копирую текущий переданный контекст в пустышку. Затем я добавляю метод fn в качестве текущей переданной функции. Фиктивный объект существует в замыкании. Наконец, я верну функцию, которая выполняет dummy.fn с первоначально переданными аргументами.

Function.prototype.bind2 = function(context, ...args){
    var dummy = {...context}
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

Редактировать 1: После первого предложения для нового фиктивного объекта я изменил его на следующий

Function.prototype.bind2 = function(context, ...args){
    var dummy = Object.create(context)
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

Редактировать 2: для исправления оператора распространения я использовал eval:

Function.prototype.bind2 = function(){
    var args = arguments;
    var dummy = Object.create(args[0]);
    dummy.fn = this;
    return function(){
                return eval('dummy.fn('+Object.values(args).slice(1,).join(',')+')') 
           } 
}

1 Ответ

3 голосов
/ 17 февраля 2020

Нет, на первый взгляд, есть несколько проблем:

  • bind вызовет метод в переданном контексте, а не в его копии - ваша версия делает невозможным связанная функция для непосредственного воздействия на контекст

  • Используемый метод копирования объекта вырезает объект из его прототипа, а также любые маги c, которые могут иметь

  • bind также позволит функции принимать дополнительные параметры, которые не связаны

  • Любая среда, которая потребует bind для заполнения, не будет способен обрабатывать синтаксис ....

Function.prototype.bind2 = function(context, ...args){
    var dummy = {...context}
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

let obj = Object.create({
  name: "an obj",
  getName: function() { return this.name; },
  setFoo: function() { this.foo = 42; },
  showBarBaz: function(bar, baz) { console.log(bar, baz) }
});
obj.setFoo.bind2(obj)();                 // does not set `obj.foo`
console.log(obj);
console.log(obj.getName.bind2(obj)());   // no access to prototype
obj.showBarBaz.bind2(obj, "bar")("baz"); // does not pass "baz"

obj.setFoo.bind(obj)();                  // sets `obj.foo`
console.log(obj);
console.log(obj.getName.bind(obj)());    // full access to prototype
obj.showBarBaz.bind(obj, "bar")("baz");  // passes "baz"
...