Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 8 题:手写代码,简单实现bind #8

Open
airuikun opened this issue Apr 8, 2019 · 10 comments
Open

第 8 题:手写代码,简单实现bind #8

airuikun opened this issue Apr 8, 2019 · 10 comments

Comments

@airuikun
Copy link
Owner

airuikun commented Apr 8, 2019

Function.prototype.bind2 = function(context) {
    var _this = this;
    var argsParent = Array.prototype.slice.call(arguments, 1);
    return function() {
        var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
        _this.apply(context, args);
    };
}
@nelsonkuang
Copy link

ES6版本

Function.prototype.bind2 = function() {
    var fn = this;
    var argsParent = [...arguments];
    return function() {
        fn.call(...argsParent, ...arguments);
    };
}
`

@lichenabson
Copy link

不使用 call apply方法

    Function.prototype.bind = function() {
        const context = arguments[0] || window
        const argument = Array.from(arguments).splice(1, arguments.length - 1)
        return (()=>{
            context.fn = this
            context.fn(...argument)
            delete context.fn
        })
    }

@xuemin-li
Copy link

为什么还要有下面这一步呢?
var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
直接_this.apply(context, argsParent);试了下也能运行~

@biubiupiu1
Copy link

不使用 call apply方法

    Function.prototype.bind = function() {
        const context = arguments[0] || window
        const argument = Array.from(arguments).splice(1, arguments.length - 1)
        return (()=>{
            context.fn = this
            context.fn(...argument)
            delete context.fn
        })
    }

应该是这样吧

Function.prototype.bind2 = function () {
        const context = arguments[0] || window
        const argument = Array.from(arguments).splice(1, arguments.length - 1)
        context.fn = this;
        return function ()  {
            context.fn(...argument, ...arguments);
            delete context.fn
        }
    }

@Kaltsit163
Copy link

Kaltsit163 commented May 21, 2019

为什么还要有下面这一步呢?
var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
直接_this.apply(context, argsParent);试了下也能运行~

我也想问这个问题;

    const app = {
        name: 'app',
        getName(version) {
            console.log(this.name + ': ' + version)
        }
    };
    Function.prototype.bind2 = function () {
        var fn = this;
        var argsParent = [...arguments];
        return function () {
            fn.call(...argsParent);
        };
    };
    app.getName.bind2({ name: 'hello' }, 1.1)(); 
    // 等价 app.getName.bind2.call(app.getName, { name: 'hello' }, 1.1);

此时bin2内,获取的上下文应该为this,也就是 fn 是为 app.getName 这个函数, 此时要让其绑定上下文至 arguments 的第一个参数,我觉得上述就可以了呢,是我疏忽了什么嘛?

好吧,我懂了

     return function () {
         fn.call(...argsParent,  ...arguments);
     };

    // 这里后面的一个 arguments 是 return 的函数的 arguments,不是外层函数的;
    // 我之前弄混淆了,之所以需要合并这个参数,是因为会有下面这种调用
    // 不这么做的话,新的函数就无法接受参数
    // bind 宗旨就是返回一个,重新绑定上下文的函数

    app.getName.bind2({ name: 'hello' }, 1.1)(2.2); 

@youngjuning
Copy link

youngjuning commented Feb 19, 2020

参考 《JavaScript高级程序设计》函数绑定:

```js
Function.prototype.bind1 = function(context) {
  var that = this
  return function() {
    that.apply(context, arguments)
  }
}
var person = { name:"杨俊宁" }
function sayHi(name) {
  console.log(this, name)
}
sayHi.bind1(person)() // {name: "杨俊宁"} undefined

@SaebaRyoo
Copy link

为什么还要有下面这一步呢?
var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
直接_this.apply(context, argsParent);试了下也能运行~

有一种情况,在bind绑定函数的时候传实参,然后在调用bind返回的函数的时候,又传一次实参。
这里就是为了解决这种情况,
比如:

function f(a, b) {
    console.log(a,b)
    console.log('this', this)
}
var obj = {name: 'william', age: 23}
f.bind(obj, 'a')('b')

其实还有一种情况需要考虑,bind函数的返回函数在作为构造函数,使用new创建对象时,提供的this值绑定会失效,可以使用如下方案。具体请看

Function.prototype.bind = function(context) {
  var context = context || window;
  var self = this;
  var bindArgs = [].slice.call(arguments, 1);

  function NOP() {};
  NOP.prototype = this.prototype;

  var Bound = function() {
    return self.apply(this instanceof NOP ? this : context, bindArgs.concat([].slice.call(arguments)))
  }

  Bound.prototype = new NOP();

  return Bound;
}

@kaeldxy
Copy link

kaeldxy commented Jun 20, 2020

Object.assign(Function.prototype, {
bind2: function (thisArg, ...arg) {
return (...params) => (thisArg.fn = this, thisArg.fn(...arg, ...params))
}
})

@jangdelong
Copy link

ES6版本

Function.prototype.bind2 = function() {

    var fn = this;

    var argsParent = [...arguments];

    return function() {

        fn.call(...argsParent, ...arguments);

    };

}

`

为什么要用ES6版本呢,==

@reson91
Copy link

reson91 commented Sep 22, 2020

不使用 call apply方法

    Function.prototype.bind = function() {
        const context = arguments[0] || window
        const argument = Array.from(arguments).splice(1, arguments.length - 1)
        return (()=>{
            context.fn = this
            context.fn(...argument)
            delete context.fn
        })
    }

第二个arguments有问题,箭头函数没有自己的arguments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests