bind、call、apply
区别
call和apply
call和apply都是为了解决改变this的指向。作?都是相同的,只是传参的?式不同。
第?个参数是一个对象,除此之外, call可以接收?个参数列表,apply只接受?个数组参数
let a = { value: 1 } function getValue(name, age) { console.log(name) console.log(age) console.log(this.value) } getValue.call(a, 'yck', '24') getValue.apply(a, ['yck', '24'])
bind
bind 和其他两个?法作?也是?致的,只是该?法会返回?个函数。并且我们可以通过 bind 实现柯?化
实现
思路:如果不传?第?个参数,那么默认为window
三个方法改变了 this 指向,让新的对象可以执?该函数。那么思路是否可以变成给新的对象添加?个函数,然后在执?完以后删除?
.bind()
bind()
方法创建一个新的函数,在 bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
const module = { x: 42, getX: function() { return this.x; } }; const unboundGetX = module.getX; console.log(unboundGetX()); // The function gets invoked at the global scope // expected output: undefined const boundGetX = unboundGetX.bind(module); console.log(boundGetX()); // expected output: 42
实现?个自己的bind函数
Function.prototype.myBind = function(context) { if (typeof this !== 'function') { throw new TypeError('Error') } var _this = this var args = [...arguments].slice(1) // 返回?个函数 return function F() { // 因为返回了?个函数,我们可以 new F(),所以需要判断 if (this instanceof F) { return new _this(...args, ...arguments) } return _this.apply(context, args.concat(...arguments)) } }
.call()
call()
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'foot'; } console.log(new Food('cheese', 5).name);
实现?个自己的call函数
Function.prototype.myCall = function(context) { var context = context || window // 给 context 添加?个属性 // getValue.call(a, 'yck', '24') => a.fn = getValue context.fn = this // 将 context 后?的参数取出来 var args = [...arguments].slice(1) // getValue.call(a, 'yck', '24') => a.fn('yck', '24') var result = context.fn(...args) // 删除 fn delete context.fn return result }
.apply()
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
const numbers = [5, 6, 2, 3, 7]; const max = Math.max.apply(null, numbers); console.log(max); // expected output: 7 const min = Math.min.apply(null, numbers); console.log(min); // expected output: 2
实现一个自己的apply函数
Function.prototype.myApply = function(context) { var context = context || window context.fn = this var result // 需要判断是否存储第?个参数 // 如果存在,就将第?个参数展开 if (arguments[1]) { result = context.fn(...arguments[1]) } else { result = context.fn() } delete context.fn return result }