1. /**
    2. * call实现
    3. * 实现原理:方法内部的this一般在调用时确定,将fn赋值给thisArg的一个方法,
    4. * 然后执行,之后再将thisArg上的fn删除,最后返回结果
    5. * apply与此相似
    6. */
    7. // fn.call(thisArg, 其他参数)
    8. Function.prototype.myCall = function () {
    9. // 判断拥有myCall的方法是不是函数
    10. if (typeof this !== 'function') {
    11. throw new TypeError(`${this} is not a function`)
    12. }
    13. const args = [...arguments]
    14. const thisArg = args.shift() || window
    15. // 方法内部的this指向在方法调用时确定,指向方法所属的对象thisArg
    16. thisArg.fn = this
    17. const result = thisArg.fn(...args)
    18. // 删除fn
    19. delete thisArg.fn
    20. return result
    21. }
    22. /**
    23. * aplly实现
    24. */
    25. Function.prototype.myApply = function () {
    26. // 判断拥有myApply的方法是不是函数
    27. if (typeof this !== 'function') {
    28. throw new TypeError(`${this} is not a function`)
    29. }
    30. const args = [...arguments]
    31. const thisArg = args.shift() || window
    32. // 方法内部的this指向在方法调用时确定,指向方法所属的对象thisArg
    33. thisArg.fn = this
    34. const result = thisArg.fn(...args[0])
    35. // 删除fn
    36. delete thisArg.fn
    37. return result
    38. }
    39. /**
    40. * bind实现
    41. * 注意:bind最终返回一个函数,作为构造函数使用new调用时,不应该改变this指向,
    42. * 因为new绑定优先级高于显示绑定和硬绑定,
    43. * new > 显示绑定 > 隐式绑定 > 默认绑定
    44. *
    45. * 实现原理:bind实现依赖于call或者apply,绑定过程分三个步骤
    46. * 1、返回一个函数
    47. * 2、参数绑定
    48. * 3、使用new
    49. *
    50. */
    51. // 效果
    52. function foo(x, y) {
    53. console.log(this)
    54. this.x = x
    55. this.y = y
    56. }
    57. const obj = {
    58. props: '007'
    59. }
    60. const bindFoo = foo.bind(obj, 'hello')
    61. foo(1, 2) // window
    62. bindFoo('world') // obj
    63. new bindFoo('newWorld')
    64. // 解释:
    65. // a步骤:const bindFoo = foo.bind(obj)相当于指定foo内部的this为obj,并返回一个函数
    66. // b步骤:new bindFoo(),因为new的优先级高于aplly,所以a步骤绑定的this失效,this现在指向new创建的实例
    67. // 实现
    68. Function.prototype.myBind = function () {
    69. if (typeof this !== 'function') {
    70. throw new TypeError('Bind must be called on a function')
    71. }
    72. const args = [...arguments]
    73. const thisArg = args.shift()
    74. console.log('外层', args)
    75. const selfFn = this
    76. return function F(...innerArgs) {
    77. const concatArgs = [...args, ...arguments]
    78. console.log(this instanceof F)
    79. return this instanceof F
    80. ? new selfFn(...concatArgs)
    81. : selfFn.apply(thisArg, concatArgs)
    82. }
    83. }
    84. // 测试代码
    85. function foo(x, y) {
    86. this.x = x
    87. this.y = y
    88. }
    89. const obj = {
    90. props: '007'
    91. }
    92. const bindFoo = foo.myBind(obj, 'hello')
    93. foo(1, 2) // window
    94. bindFoo('world') // obj
    95. new bindFoo('newWorld')