确定API

  • 特殊性
    • bind位于Function.prototype上
    • 需要做polyfill
  • API
    • fn.bind(asThis)
    • fn.bind(asThis,param1,param2)
    • fn.bind(asThis)()
    • fn.bind(asThis,param1,param2)()
    • fn.bind(asThis)(param1)
    • fn.bind(asThis,param1,param2)(p3,p4)

      代码

/src/index.js

  1. var slice = Array.prototype.slice
  2. //ES6
  3. function _bind(asThis, ...args) {
  4. //this 就是绑定bind前的那个函数
  5. var fn = this
  6. return function (...args2) {
  7. return fn.call(asThis, ...args, ...args2)
  8. }
  9. }
  10. // 不用拓展运算符 ES3
  11. function bind(asThis) {
  12. var args = slice.call(arguments, 1)
  13. //this 就是绑定bind前的那个函数
  14. var fn = this
  15. if (typeof fn !== 'function') {
  16. throw new Error('bind必须用在函数上')
  17. }
  18. return function () {
  19. var args2 = slice.call(arguments, 0)
  20. return fn.apply(asThis, args.concat(args2))
  21. }
  22. }
  23. module.exports = bind
  24. if (!Function.prototype.bind) {
  25. Function.prototype.bind = bind
  26. }

/test/index.js

  1. const bind = require("../src/index")
  2. Function.prototype.bind2 = bind
  3. console.assert(Function.prototype.bind2 !== undefined)
  4. //1 fn.bind(asThis)
  5. const fn1 = function () {
  6. return this
  7. }
  8. const newFn1 = fn1.bind2({
  9. name: "gouson"
  10. })
  11. console.assert(newFn1().name === 'gouson')
  12. //2 fn.bind(asThis,param1,param2)
  13. const fn2 = function (p1, p2) {
  14. return [this, p1, p2]
  15. }
  16. const newFn2 = fn2.bind2({
  17. name: 'gouson'
  18. }, 123, 456)
  19. console.assert(newFn2()[0].name === 'gouson')
  20. console.assert(newFn2()[1] === 123)
  21. console.assert(newFn2()[2] === 456)
  22. //3 fn.bind(asThis)()
  23. const anotherFn2 = fn2.bind2({
  24. name: 'gouson'
  25. })
  26. console.assert(anotherFn2(223,224)[0].name === 'gouson')
  27. console.assert(anotherFn2(223,224)[1] === 223)
  28. console.assert(anotherFn2(223,224)[2] === 224)

支持new

过程

  1. var temp={}
  2. temp.proto = fn.prototype
  3. fn.call(temp,’x’)
  4. return this
  1. var slice = Array.prototype.slice
  2. //ES6 阅读
  3. function _bind(asThis, ...args) {
  4. //this 就是绑定bind前的那个函数
  5. var fn = this
  6. function resultFn(...args2) {
  7. //new会做的事情
  8. //this //new 生成的
  9. //this.__proto__=resultFn.prototype
  10. //this.p1="x"
  11. //this.p2="y"
  12. //return this ;//这里 因为下面的return消失了,所以无法饭会这个this
  13. //this.constructor === resultFn 可能是继承的
  14. //this.__proto__ === resultFn.prototype 无法保证一定是new
  15. return fn.call(
  16. //resultFn.prototype.isPrototypeOf(this) 这个可以判断,es3就有
  17. this instanceof resultFn ? this : asThis,
  18. ...args,
  19. ...args2)
  20. }
  21. resultFn.prototype = fn.prototype
  22. return resultFn
  23. }
  24. // 不用拓展运算符 ES3
  25. function bind(asThis) {
  26. var args = slice.call(arguments, 1)
  27. var fn = this
  28. if (typeof fn !== 'function') {
  29. throw new Error('必须是函数')
  30. }
  31. function resultFn() {
  32. var args2 = slice.call(arguments, 0)
  33. return fn.apply(
  34. resultFn.prototype.isPrototypeOf(this) ? this : asThis,
  35. rgs.concat(args2)
  36. )
  37. }
  38. resultFn.prototype = fn.prototype
  39. return resultFn
  40. }
  41. module.exports = bind
  42. if (!Function.prototype.bind) {
  43. Function.prototype.bind = bind
  44. }

/测试

  1. const bind = require("../src/index")
  2. Function.prototype.bind2 = bind
  3. console.assert(Function.prototype.bind2 !== undefined)
  4. test1('this绑定成功')
  5. test2('this,p1,p2绑定成功')
  6. test3('this,p1绑定成功,p2后传执成功')
  7. test4('new 绑定p1,p2')
  8. test5('new 绑定function sayHi')
  9. test5('不用new 用类似一个对象')
  10. //1 fn.bind(asThis)
  11. function test1(message) {
  12. const fn = function () {
  13. return this
  14. }
  15. const newFn = fn.bind2({
  16. name: "gouson"
  17. })
  18. console.assert(newFn().name === 'gouson')
  19. console.log(message)
  20. }
  21. //2 fn.bind(asThis,param1,param2)
  22. function test2(message) {
  23. const fn = function (p1, p2) {
  24. return [this, p1, p2]
  25. }
  26. const newFn = fn.bind2({
  27. name: 'gouson'
  28. }, 123, 456)
  29. console.assert(newFn()[0].name === 'gouson')
  30. console.assert(newFn()[1] === 123)
  31. console.assert(newFn()[2] === 456)
  32. console.log(message)
  33. }
  34. //3 fn.bind(asThis)()
  35. function test3(message) {
  36. const fn = function (p1, p2) {
  37. return [this, p1, p2]
  38. }
  39. const anotherFn = fn.bind2({
  40. name: 'gouson'
  41. })
  42. console.assert(anotherFn(223, 224)[0].name === 'gouson')
  43. console.assert(anotherFn(223, 224)[1] === 223)
  44. console.assert(anotherFn(223, 224)[2] === 224)
  45. console.log(message)
  46. }
  47. //4 fn.bind(asThis)()
  48. function test4(message) {
  49. const fn = function (p1, p2) {
  50. this.p1 = p1
  51. this.p2 = p2
  52. }
  53. const fn2 = fn.bind2(undefined, 'x', 'y')
  54. const object = new fn2()
  55. console.assert(object.p1 === 'x', 'x')
  56. console.assert(object.p2 === 'y', 'y')
  57. console.log(message)
  58. }
  59. function test5(message) {
  60. const fn = function (p1, p2) {
  61. this.p1 = p1
  62. this.p2 = p2
  63. }
  64. fn.prototype.sayHi = function () {}
  65. const fn2 = fn.bind2(undefined, 'x', 'y')
  66. const object = new fn2()
  67. console.assert(object.p1 === 'x', 'x')
  68. console.assert(object.p2 === 'y', 'y')
  69. console.assert(object.__proto__ === fn.prototype)
  70. console.assert(typeof object.sayHi === "function")
  71. console.log(message)
  72. }
  73. function test6(message) {
  74. const fn = function (p1, p2) {
  75. this.p1 = p1
  76. this.p2 = p2
  77. }
  78. fn.prototype.sayHi = function () {}
  79. const object1 = new fn('a', 'b')
  80. const fn2 = fn.bind2(object1, 'x', 'y')
  81. const object = fn2()
  82. console.assert(object === undefined, 'object为空')
  83. console.assert(object1.p1 === 'x', 'x')
  84. console.assert(object1.p2 === 'y', 'y')
  85. console.log(message)
  86. }