call 概念 MDN 对call()
方法的解释是:
call()
方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
也就是说:一个对象可以使用call()
来调用另一个对象的方法,相当于设置被调用方法内this
的值。可以扩充函数的作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 var color = 'red' ;var obj = { color: 'green' }; function showColor (color ) { this .color = color || this .color; console .log(this .color); } showColor(); showColor.call(obj, 'blue' );
call的语法 1 func.call(thisArg, arg1, arg2, ...)
实现方法:
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.myCall = function (context ) { context = context || window ; context.func = this ; let args = []; for (let i = 1 ; i < arguments .length; i++) { args.push(arguments [i]); } context.func(...args) delete context.func; } Function .prototype.myCall = function (context ) { context = context || window ; context.func = this ; var args = []; for (var i = 1 ; i < arguments .length; i++) { args.push('arguments[' + i + ']' ); } eval ('context.func(' + args + ')' ) delete context.func; }
用法 使用call()
方法调用父构造函数实现继承 可以通过调用父构造函数的call()
方法来实现继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function Product (name, price ) { this .name = name; this .price = price; this .showPrice = function ( ) { console .log(this .price); } } function Food (name, price ) { Product.call(this , name, price); this .category = 'food' ; } var apple = new Food('apple' , 5 );apple.showPrice();
使用call()
方法调用匿名函数 1 2 3 4 5 6 7 8 9 10 var objArr = [ { index : 0 , name : 'a' }, { index : 1 , name : 's' } ]; for (let i = 0 ; i < objArr.length; i++) { (function (i ) { console .log(i + ': ' + this .name); }).call(objArr[i], i); }
apply call()
方法的作用和apply()
方法类似,区别就是call()
方法接受的是参数列表,而apply()
方法接受的是一个参数数组
语法 1 func.apply(thisArg, [argsArray])
1 2 3 4 5 function add (x, y, z ) { console .log(x + y + z); } add.apply(this , [1 , 2 , 3 ])
实现方法:
1 2 3 4 5 6 7 8 9 10 11 Function .prototype.myApply = function (context, arr ) { context = context || window ; context.func = this ; if (!arr) { context.func(); } else { context.func(...arr); } delete context.func; }
用途 将数组转换成列表 类似于ES6的...
1 2 3 4 5 var arr1 = [1 , 2 ], arr2 = [3 , 4 ]; arr1.push(...arr2) arr1.push.apply(arr1, arr2)
类似的,也可以用在Math.max()
和Math.min()
等方法上
bind bind()
方法创建一个新的函数实例,其this
值会被绑定到传给bind()
函数的值
1 2 3 4 5 6 global.x = 1 ; var obj = { x : 10 };(function ( ) { console .log(this .x); }.bind(obj))();
语法 1 function .bind (thisArg[, arg1[, arg2[, ...]]] )
实现方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Function .prototype.myBind = function (obj ) { var self = this , boundArgs = arguments ; return function ( ) { var args = [], i; for (i = 1 ; i < boundArgs.length; i++) { args.push(boundArgs[i]); } for (i = 0 ; i < arguments .length; i++) { args.push(arguments [i]); } return self.apply(obj, args); } }
用途 创建绑定函数 bind()
可以创建一个函数,不论怎么调用,这个函数都有同样的this
值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 global.x = 1 ; var obj = { x: 10 , getX: function ( ) { console .log(this .x); } }; obj.getX(); var oneGetX = obj.getX;oneGetX(); var anotherGetX = obj.getX.bind(obj);anotherGetX();
让函数拥有预设的参数 bind()
可以使一个函数拥有预设的初始参数,只要将这些参数作为bind()
的参数写在this后面
1 2 3 4 5 6 7 8 9 10 11 function list ( ) { return Array .prototype.slice.call(arguments ); } console .log(list(1 , 2 , 3 )); var anotherList = list.bind(null , 10 );console .log(anotherList()); console .log(anotherList(1 , 2 , 3 ));
与setTimeout一起使用 正常情况下,调用setTimeout
的时候this
会指向全局对象,但是使用类的方法时我们需要指向类的实例,所以要把this
绑定到回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function f ( ) { this .x = 1 ; } f.prototype.say1 = function ( ) { window .setTimeout(this .show.bind(this ), 2000 ); } f.prototype.say2 = function ( ) { window .setTimeout(this .show, 2000 ); } f.prototype.show = function ( ) { console .log(this .x); } var obj = new f();obj.say1(); obj.say2();