确定API
- 特殊性
- bind位于Function.prototype上
- 需要做polyfill
- API
/src/index.js
var slice = Array.prototype.slice//ES6function _bind(asThis, ...args) {//this 就是绑定bind前的那个函数var fn = thisreturn function (...args2) {return fn.call(asThis, ...args, ...args2)}}// 不用拓展运算符 ES3function bind(asThis) {var args = slice.call(arguments, 1)//this 就是绑定bind前的那个函数var fn = thisif (typeof fn !== 'function') {throw new Error('bind必须用在函数上')}return function () {var args2 = slice.call(arguments, 0)return fn.apply(asThis, args.concat(args2))}}module.exports = bindif (!Function.prototype.bind) {Function.prototype.bind = bind}
/test/index.js
const bind = require("../src/index")Function.prototype.bind2 = bindconsole.assert(Function.prototype.bind2 !== undefined)//1 fn.bind(asThis)const fn1 = function () {return this}const newFn1 = fn1.bind2({name: "gouson"})console.assert(newFn1().name === 'gouson')//2 fn.bind(asThis,param1,param2)const fn2 = function (p1, p2) {return [this, p1, p2]}const newFn2 = fn2.bind2({name: 'gouson'}, 123, 456)console.assert(newFn2()[0].name === 'gouson')console.assert(newFn2()[1] === 123)console.assert(newFn2()[2] === 456)//3 fn.bind(asThis)()const anotherFn2 = fn2.bind2({name: 'gouson'})console.assert(anotherFn2(223,224)[0].name === 'gouson')console.assert(anotherFn2(223,224)[1] === 223)console.assert(anotherFn2(223,224)[2] === 224)
支持new
过程
- var temp={}
- temp.proto = fn.prototype
- fn.call(temp,’x’)
- return this
var slice = Array.prototype.slice//ES6 阅读function _bind(asThis, ...args) {//this 就是绑定bind前的那个函数var fn = thisfunction resultFn(...args2) {//new会做的事情//this //new 生成的//this.__proto__=resultFn.prototype//this.p1="x"//this.p2="y"//return this ;//这里 因为下面的return消失了,所以无法饭会这个this//this.constructor === resultFn 可能是继承的//this.__proto__ === resultFn.prototype 无法保证一定是newreturn fn.call(//resultFn.prototype.isPrototypeOf(this) 这个可以判断,es3就有this instanceof resultFn ? this : asThis,...args,...args2)}resultFn.prototype = fn.prototypereturn resultFn}// 不用拓展运算符 ES3function bind(asThis) {var args = slice.call(arguments, 1)var fn = thisif (typeof fn !== 'function') {throw new Error('必须是函数')}function resultFn() {var args2 = slice.call(arguments, 0)return fn.apply(resultFn.prototype.isPrototypeOf(this) ? this : asThis,rgs.concat(args2))}resultFn.prototype = fn.prototypereturn resultFn}module.exports = bindif (!Function.prototype.bind) {Function.prototype.bind = bind}
/测试
const bind = require("../src/index")Function.prototype.bind2 = bindconsole.assert(Function.prototype.bind2 !== undefined)test1('this绑定成功')test2('this,p1,p2绑定成功')test3('this,p1绑定成功,p2后传执成功')test4('new 绑定p1,p2')test5('new 绑定function sayHi')test5('不用new 用类似一个对象')//1 fn.bind(asThis)function test1(message) {const fn = function () {return this}const newFn = fn.bind2({name: "gouson"})console.assert(newFn().name === 'gouson')console.log(message)}//2 fn.bind(asThis,param1,param2)function test2(message) {const fn = function (p1, p2) {return [this, p1, p2]}const newFn = fn.bind2({name: 'gouson'}, 123, 456)console.assert(newFn()[0].name === 'gouson')console.assert(newFn()[1] === 123)console.assert(newFn()[2] === 456)console.log(message)}//3 fn.bind(asThis)()function test3(message) {const fn = function (p1, p2) {return [this, p1, p2]}const anotherFn = fn.bind2({name: 'gouson'})console.assert(anotherFn(223, 224)[0].name === 'gouson')console.assert(anotherFn(223, 224)[1] === 223)console.assert(anotherFn(223, 224)[2] === 224)console.log(message)}//4 fn.bind(asThis)()function test4(message) {const fn = function (p1, p2) {this.p1 = p1this.p2 = p2}const fn2 = fn.bind2(undefined, 'x', 'y')const object = new fn2()console.assert(object.p1 === 'x', 'x')console.assert(object.p2 === 'y', 'y')console.log(message)}function test5(message) {const fn = function (p1, p2) {this.p1 = p1this.p2 = p2}fn.prototype.sayHi = function () {}const fn2 = fn.bind2(undefined, 'x', 'y')const object = new fn2()console.assert(object.p1 === 'x', 'x')console.assert(object.p2 === 'y', 'y')console.assert(object.__proto__ === fn.prototype)console.assert(typeof object.sayHi === "function")console.log(message)}function test6(message) {const fn = function (p1, p2) {this.p1 = p1this.p2 = p2}fn.prototype.sayHi = function () {}const object1 = new fn('a', 'b')const fn2 = fn.bind2(object1, 'x', 'y')const object = fn2()console.assert(object === undefined, 'object为空')console.assert(object1.p1 === 'x', 'x')console.assert(object1.p2 === 'y', 'y')console.log(message)}
