确定API
- 特殊性
- bind位于Function.prototype上
- 需要做polyfill
- API
/src/index.js
var slice = Array.prototype.slice
//ES6
function _bind(asThis, ...args) {
//this 就是绑定bind前的那个函数
var fn = this
return function (...args2) {
return fn.call(asThis, ...args, ...args2)
}
}
// 不用拓展运算符 ES3
function bind(asThis) {
var args = slice.call(arguments, 1)
//this 就是绑定bind前的那个函数
var fn = this
if (typeof fn !== 'function') {
throw new Error('bind必须用在函数上')
}
return function () {
var args2 = slice.call(arguments, 0)
return fn.apply(asThis, args.concat(args2))
}
}
module.exports = bind
if (!Function.prototype.bind) {
Function.prototype.bind = bind
}
/test/index.js
const bind = require("../src/index")
Function.prototype.bind2 = bind
console.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 = this
function 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 无法保证一定是new
return fn.call(
//resultFn.prototype.isPrototypeOf(this) 这个可以判断,es3就有
this instanceof resultFn ? this : asThis,
...args,
...args2)
}
resultFn.prototype = fn.prototype
return resultFn
}
// 不用拓展运算符 ES3
function bind(asThis) {
var args = slice.call(arguments, 1)
var fn = this
if (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.prototype
return resultFn
}
module.exports = bind
if (!Function.prototype.bind) {
Function.prototype.bind = bind
}
/测试
const bind = require("../src/index")
Function.prototype.bind2 = bind
console.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 = p1
this.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 = p1
this.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 = p1
this.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)
}