{"action":"opened","issue":{"url":"https://api.github.com/repos/webfansplz/blog/issues/8","repository_url":"https://api.github.com/repos/webfansplz/blog","labels_url":"https://api.github.com/repos/webfansplz/blog/issues/8/labels{/name}","comments_url":"https://api.github.com/repos/webfansplz/blog/issues/8/comments","events_url":"https://api.github.com/repos/webfansplz/blog/issues/8/events","html_url":"https://github.com/webfansplz/blog/issues/8","id":301988087,"number":8,"title":"call,apply,bind 模拟实现与区别","user":{"login":"webfansplz","id":22515951,"avatar_url":"https://avatars1.githubusercontent.com/u/22515951?v=4","gravatar_id":"","url":"https://api.github.com/users/webfansplz","html_url":"https://github.com/webfansplz","followers_url":"https://api.github.com/users/webfansplz/followers","following_url":"https://api.github.com/users/webfansplz/following{/other_user}","gists_url":"https://api.github.com/users/webfansplz/gists{/gist_id}","starred_url":"https://api.github.com/users/webfansplz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/webfansplz/subscriptions","organizations_url":"https://api.github.com/users/webfansplz/orgs","repos_url":"https://api.github.com/users/webfansplz/repos","events_url":"https://api.github.com/users/webfansplz/events{/privacy}","received_events_url":"https://api.github.com/users/webfansplz/received_events","type":"User","site_admin":false},"labels":[{"id":809416919,"url":"https://api.github.com/repos/webfansplz/blog/labels/javascript","name":"javascript","color":"d4c5f9","default":false},{"id":815192412,"url":"https://api.github.com/repos/webfansplz/blog/labels/%E5%89%8D%E7%AB%AF","name":"前端","color":"fbca04","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-03T10:40:44Z","updated_at":"2018-03-03T10:40:44Z","closed_at":null,"author_association":"OWNER","body":"# call,apply,bind 的模拟实现与区别\r\n\r\n## 一.用途与区别\r\n\r\n### 1.用途\r\n\r\ncall:call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。\r\n\r\napply:apply() 方法在使用一个指定的 this 值和一个数组作为参数的前提下调用某个函数或方法。\r\n\r\nbind:bind() 方法在使用一个指定的 this 值和对应参数来重新绑定方法/函数的 this 指向。\r\n\r\n### 2.区别\r\n\r\n1.call 接收的是多个数值,apply 接收的是一个数组.\r\n\r\n2.call/apply 立即调用函数/方法,bind 返回对函数/方法的引用 (稍后引用).\r\n\r\n## 二.模拟实现\r\n\r\n### 1.call\r\n\r\nES3(转):\r\n\r\n```\r\nFunction.prototype.call1 = function (context) {\r\n    var context = context || window;\r\n    context.fn = this;\r\n\r\n    var args = [];\r\n    for(var i = 1, len = arguments.length; i < len; i++) {\r\n        args.push('arguments[' + i + ']');\r\n    }\r\n    var result = eval('context.fn(' + args +')');\r\n\r\n    delete context.fn\r\n    return result;\r\n}\r\n```\r\n\r\nES6:\r\n\r\n```\r\nFunction.prototype.call1 = function(c) {\r\n  const cxt = c || window;\r\n  cxt.fn = this;\r\n  let args = Array.from(arguments);\r\n  args.shift();\r\n  let res = args.length > 0 ? cxt.fn(...args) : cxt.fn();\r\n  delete cxt.fn;\r\n  return res;\r\n};\r\n```\r\n\r\n### 2.apply\r\n\r\nES3(转):\r\n\r\n```\r\nFunction.prototype.apply1 = function (context, arr) {\r\n    var context = Object(context) || window;\r\n    context.fn = this;\r\n\r\n    var result;\r\n    if (!arr) {\r\n        result = context.fn();\r\n    }\r\n    else {\r\n        var args = [];\r\n        for (var i = 0, len = arr.length; i < len; i++) {\r\n            args.push('arr[' + i + ']');\r\n        }\r\n        result = eval('context.fn(' + args + ')')\r\n    }\r\n\r\n    delete context.fn\r\n    return result;\r\n}\r\n```\r\n\r\nES6:\r\n\r\n```\r\nFunction.prototype.apply1 = function(c) {\r\n  let cxt = c || window;\r\n  cxt.fn = this;\r\n  let res = arguments[1] ? cxt.fn(...arguments[1]) : cxt.fn();\r\n  delete cxt.fn;\r\n  return res;\r\n};\r\n```\r\n\r\n### 3.bind\r\n\r\nES3(转):\r\n\r\n```\r\nFunction.prototype.bind1 = function (context) {\r\n\r\n    if (typeof this !== \"function\") {\r\n      throw new Error(\"Function.prototype.bind - what is trying to be bound is not callable\");\r\n    }\r\n\r\n    var self = this;\r\n    var args = Array.prototype.slice.call(arguments, 1);\r\n\r\n    var fNOP = function () {};\r\n\r\n    var fBound = function () {\r\n        var bindArgs = Array.prototype.slice.call(arguments);\r\n        return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));\r\n    }\r\n\r\n    fNOP.prototype = this.prototype;\r\n    fBound.prototype = new fNOP();\r\n    return fBound;\r\n}\r\n```\r\n\r\nES6:\r\n\r\n```\r\nFunction.prototype.bind1 = function(c) {\r\n  let cxt = JSON.parse(JSON.stringify(c)) || window;\r\n  cxt.fn = this;\r\n  let args = Array.from(arguments);\r\n  args.shift();\r\n  return () => {\r\n    let res = args.length > 0 ? cxt.fn(...args) : cxt.fn();\r\n    return res;\r\n  };\r\n};\r\n```\r\n"}}
{"actor":{"display_login":"webfansplz"}}