1.手写 apply 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Function .prototype .apply1 = function (context = window , args ) { const fn = Symbol ('fn' ) context[fn] = this const res = context[fn](...args) delete context[fn] return res } Function .prototype .apply2 = function (context ) { if (typeof this !== 'function' ) { throw new TypeError ('not funciton' ) } context = context || window context.fn = this let result if (arguments [1 ]) { result = context.fn (...arguments [1 ]) } else { result = context.fn () } delete context.fn return result }
2.手写 call 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Function .prototype .call1 = function (context = window , ...args ) { const fn = Symbol ('fn' ) context[fn] = this const res = context[fn](...args) delete context[fn] return res } Function .prototype .call2 = function (context ) { if (typeof this !== 'function' ) { throw new TypeError ('not funciton' ) } context = context || window context.fn = this let arg = [...arguments ].slice (1 ) let result = context.fn (...arg) delete context.fn return result }
3.手写 bind 方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Function .prototype .bind1 = function (context, ...args ) { let self = this return function F ( ) { if (this instanceof F) { return new self (...args, ...arguments ) } return self.apply (context, [...args, ...arguments ]) } } Function .prototype .bind2 = function (context ) { if (typeof this !== 'function' ) { throw new TypeError ('Error' ) } let _this = this let arg = [...arguments ].slice (1 ) return function F ( ) { if (this instanceof F) { return new _this (...arg, ...arguments ) } else { return _this.apply (context, arg.concat (...arguments )) } } }
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var obj = { a : 1 , showA (n, m ) { return this .a + n + m }, } function test1 ( ) { this .a = 4 var s = obj.showA .bind (this , 10 ) console .log ('result:' ,s (20 )) } function test2 ( ) { this .a = 2 var s = obj.showA .apply (this , [1 , 2 ]) console .log ('result:' , s) } function test3 ( ) { this .a = 3 var s = obj.showA .call (this , 2 , 3 ) console .log ('result:' , s) } test1 ()test2 ()test3 ()
4.实现一个 new new 关键字调用的基本过程 1)创建一个新对象 2)继承父类原型的方法 3)添加父类属性到新对象上,并初始化,并保存方法的执行结果 4)如果执行结果有返回值,并且是一个对象,返回执行的结果,否则返回新创建的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function _new1 (obj, ...args ) { var newObj = Object .create (obj.prototype ) var result = obj.apply (newObj, args) return (typeof result === 'object' && result !== null ) ? result : newObj } function _new2 (fun) { return function ( ) { let obj = { __proto__ : fun.prototype } fun.call (obj, ...arguments ) return obj } } function Person (firstName, lastName ) { this .firstName = firstName this .lastName = lastName } Person .prototype .getFullName = function ( ) { return this .firstName + ' ' + this .lastName } var newPerson = new Person ('jack' , 'bob' )var _newPerson = _new (Person , 'jack' , 'bob' )
5.手写instanceof 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function instanceOf (left, right ) { let leftValue = left.__proto__ let rightValue = right.prototype while (true ) { if (leftValue === null ) { return false } if (leftValue === rightValue) { return true } leftValue = leftValue.__proto__ } }
6.手写create 1 2 3 4 5 6 function create (obj ) { function F ( ) {} F.prototype = obj return new F () }