Arguments 对象,call()、apply()与bind()

Arguments 对象

arguments:是一个对应于传递给函数的参数的类数组对象。arguments对象是所有(非箭头)函数中都可用的局部变量,你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。

ps:arguments对象不是一个 Array ,它类似于Array,但除了length属性和索引元素之外没有任何Array属性和方法。但可以被转换为一个真正的Array,方式如下:

// ES5
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);

// ES6
const args = Array.from(arguments);
const args = [...arguments];

参考资料:

1、arguments:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments


call()、apply()、bind()——用于改变/固定this指向

call()

call():使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数:接受的是一个参数列表

call方法使用的指定的this值参数应该是一个对象,如果参数为空、nullundefined,则默认传入全局对象。

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456

call应用:调用对象的原生方法(比如对象继承的原生方法已经被覆盖,想要调用原生的方法时)

var obj = {};
obj.hasOwnProperty('toString') // false

// 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty('toString') // true

Object.prototype.hasOwnProperty.call(obj, 'toString') // false

call巧用:将具有length属性的对象转成数组[].slice.call(arguments),为了提高性能,减少对原型链的追溯,一般使用Array.prototype.slice.call(arguments)

let obj1 = {
    a: '我是obj1的a',
    fn: function(msg) {
        console.log(msg + this.a);
    }
}

let obj2 = {
    a: '我是obj2的a'
}

// 正常调用
obj1.fn('你说啥?')    // 你说啥?我是obj1的a

// call()调用
obj1.fn.call(obj2, '你说啥?')    // 你说啥?我是obj2的a

apply()

apply():使用一个指定的 this 值和单独给出的一个数组(['eat', 'bananas'])或数组对象(new Array('eat', 'bananas'))参数来调用一个函数:接受的是一个包含多个参数的数组

const numbers = [5, 6, 2, 3, 7];

const max = Math.max.apply(null, numbers);   // apply巧用,将数组转换为参数列表,等同于`Math.max(...numbers)`

console.log(max);   // expected output: 7

const min = Math.min.apply(null, numbers);

console.log(min);   // expected output: 2

apply巧用

// 应用一:找出数组的最大元素
var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15

// 应用二:将数组的空元素变为undefined
Array.apply(null, ['a', ,'b'])
// [ 'a', undefined, 'b' ]

// 应用三:转换类似数组的对象
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]

// 应用四:绑定回调函数的对象
var o = new Object();

o.f = function () {
  console.log(this === o);
}

var f = function (){
  o.f.apply(o);
  // 或者 o.f.call(o);
};

// jQuery 的写法
$('#button').on('click', f);

bind()

bind():使用一个指定的 this 值和单独给出的一个或多个参数来创建一个函数供后续被调用:接受的是一个参数列表

bind每一次都会返回一个新函数,所以在事件绑定的时候不能直接在绑定参数中直接使用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

三者的区别:callbind传参是参数列表,而apply传参是数组,callapply是一次性传入参数,而bind可以分为多次传入;bind是返回绑定this之后的函数,便于稍后调用;callapply 则是立即执行。

参考资料:

1、call():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call
2、apply():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
3、bind():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
4、展开语法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax

posted @ 2019-12-07 11:25  Dreamsqin  阅读(654)  评论(0编辑  收藏  举报