apply、call用法与区别

2019-06-1756次阅读javascript

有些JavaScript初学者会问刚开始要学习哪些框架,但是如果你还没能熟练使用原生JavaScript,你就不应该问这种问题。因为你会花很多时间研究各种框架而得不到进步。所以不要让对未来的忧虑干扰你现在的学习,不要再想将要学什么,沉浸于现在,慢下来,小步向前,你将学得更快

ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含非继承而来的方法apply()、call()、bind(),都是为了改变函数内部this的指向;

 

Function.prototype.apply()

语法

fun.apply(thisArg, [argsArray])

参数

thisArg

在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定null或undefined时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象

argsArray

一个数组或者类数组对象,其中的数组元素将作为单独的参数传给fun函数。如果该参数的值为null或undefined,则表示不需要传入任何参数。从ECMAScript5开始可以使用类数组对象

找出一个数组中的最大/最小值

var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);

monkey-patching(猴子补丁)

var originalfoo = someobject.foo;
someobject.foo = function() {
  //在调用函数前干些什么
  console.log(arguments);
  //像正常调用这个函数一样来进行调用:
  originalfoo.apply(this,arguments);
  //在这里做一些调用之后的事情。
}

类数组转换为数组

比如arguments对象,获取到的文档节点等,并没有数组的那些方法:

Array.prototype.slice.apply(arguments); //理论上来说这个比较快,直接在原型上查找slice方法,但实际上比较慢
或者
[].slice.apply(arguments); //理论上来说这个比较慢,因为要Array做一个实例化再查找slice方法,实际上比较快,因为现在的各种自动化工具会把上一种方法转换为这种,而第二种代码比较简洁,所以会比较快;

 

Function.prototype.call()

语法

fun.call(thisArg, arg1, arg2, ...)

参数

thisArg

在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象

arg1, arg2, ...

指定的参数列表

验证是否是数组(前提是toString()方法没有被重写过)

function   isArray(obj){ 
    return Object.prototype.toString.call(obj) === '[object Array]' ;
}

借用构造函数

function Product(name, price) {
  this.name = name;
  this.price = price;

  if (price < 0) {
    throw RangeError('Cannot create product ' +
                      this.name + ' with a negative price');
  }
}

function Food(name, price) {
  Product.call(this, name, price); 
  this.category = 'food';
}

//等同于
function Food(name, price) { 
    this.name = name;
    this.price = price;
    if (price < 0) {
        throw RangeError('Cannot create product ' +
                this.name + ' with a negative price');
    }

    this.category = 'food'; 
}

//function Toy 同上
function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

调用匿名函数

var animals = [
  {species: 'Lion', name: 'King'},
  {species: 'Whale', name: 'Fail'}
];

for (var i = 0; i < animals.length; i++) {
  (function (i) { 
    this.print = function () { 
      console.log('#' + i  + ' ' + this.species + ': ' + this.name); 
    } 
    this.print();
  }).call(animals[i], i);
}

指定上下文的'this'

function greet() {
  var reply = [this.person, 'Is An Awesome', this.role].join(' ');
  console.log(reply);
}

var i = {
  person: 'Douglas Crockford', role: 'Javascript Developer'
};

greet.call(i); // Douglas Crockford Is An Awesome Javascript Developer

 

apply、call之间区别

只有一个区别,就是 call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组或类数组

上一篇: 客户端存储之cookie  下一篇: bind用法与apply、call的区别  

apply、call用法与区别相关文章