JavaScript--call( )/apply( )用法

原创 2017年09月05日 23:38:52

call( )

语法

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

参数

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

arg1, arg2, …
指定的参数列表。

用法

使用call方法实现继承关系

在一个子构造函数中,你可以通过调用父构造函数的 call 方法来实现继承,类似于Java中的写法。下例中,使用 Food 和 Toy 构造函数创建的对象实例都会拥有在 Product 构造函数中添加的 name 属性和 price 属性,但 category 属性是在各自的构造函数中定义的。

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);

使用call方法调用匿名函数

在下例中的for循环体内,我们创建了一个匿名函数,然后通过调用该函数的call方法,将每个数组元素作为指定的this值执行了那个匿名函数。这个匿名函数的主要目的是给每个数组元素对象添加一个print方法,这个print方法可以打印出各元素在数组中的正确索引号。当然,这里不是必须得让数组元素作为this值传入那个匿名函数(普通参数就可以),目的是为了演示call的用法。

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);

使用call方法调用函数并且指定上下文的’this’

在下面的例子中,当调用 greet 方法的时候,该方法的 this 值会绑定到 i 对象。

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);

apply( )

语法

fun.apply(thisArg, [argsArray])

参数

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

argsArray
一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

描述

在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。

apply()call() 非常相似,不同之处在于提供参数的方式。apply 使用参数数组而不是一组参数列表。apply 可以使用数组字面量,如 fun.apply(this, ['eat', 'bananas']),或数组对象, 如 fun.apply(this, new Array('eat', 'bananas'))

你也可以使用 arguments 对象作为 argsArray 参数。 arguments 是一个函数的局部变量。 它可以被用作被调用对象的所有未指定的参数。 这样,你在使用apply函数的时候就不需要知道被调用对象的所有参数。 你可以使用arguments来把所有的参数传递给被调用对象。 被调用对象接下来就负责处理这些参数。

ECMAScript 第5版开始,可以使用任何种类的类数组对象,就是说只要有一个 length 属性和[0…length) 范围的整数属性。例如现在可以使用 NodeList 或一个自己定义的类似 {'length': 2, '0': 'eat', '1': 'bananas'} 形式的对象。

用法

使用apply来链接构造器

你可以使用apply来给一个对象链接构造器,类似于Java. 在接下来的例子中我们会创建一个叫做construct的全局的Function函数,来使你能够在构造器中使用一个类数组对象而非参数列表

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

//或者

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() { 
    fConstructor.apply(this, aArgs); 
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};

//使用

function MyConstructor () {
    for (var nProp = 0; nProp < arguments.length; nProp++) {
        this["property" + nProp] = arguments[nProp];
    }
}

var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);                // logs "Hello world!"
console.log(myInstance instanceof MyConstructor); // logs "true"
console.log(myInstance.constructor);              // logs "MyConstructor"

使用apply和内置函数

聪明的apply用法允许你在某些本来需要写成遍历数组变量的任务中使用内建的函数。在接下里的例子中我们会使用Math.max/Math.min来找出一个数组中的最大/最小值。

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

var max = Math.max.apply(null, numbers); 
var min = Math.min.apply(null, numbers);

/*普通办法*/
max = -Infinity, min = +Infinity;

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max)
    max = numbers[i];
  if (numbers[i] < min) 
    min = numbers[i];
}

但是当心:如果用上面的方式调用 apply, 你很可能会遇到方法参数个数越界的问题. 当你对一个方法传入非常多的参数 (比如超过1W多个参数) 时, 就非常有可能会导致越界问题, 这个临界值是根据不同的 JavaScript 引擎而定的 (JavaScript 核心中已经做了硬编码 参数个数限制在65536),因为这个限制(实际上也是任何用到超大栈空间的行为的自然表现)是未指定的. 有些引擎会抛出异常. 更糟糕的是其他引擎会直接限制传入到方法的参数个数,导致参数丢失. (举个例子: 如果某个引擎限制了方法参数最多为4个 [实际真正的参数个数限制当然要高得多了, 这里只是打个比方], 上面的代码中, 真正通过 apply 传到目标方法中的参数为 5, 6, 2, 3, 而不是完整的 numbers 数组.) 如果你的参数数组可能非常大, 那么推荐使用下面这种策略来处理: 将参数数组切块后循环传入目标方法:

function minOfArray(arr) {
  var min = Infinity;
  var QUANTUM = 32768;

  for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
    var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
    min = Math.min(submin, min);
  }

  return min;
}

var min = minOfArray([5, 6, 2, 3, 7]);
版权声明:原创文章,如想转载,请注明原文网址,注明出处;否则,禁止转载;谢谢配合! https://blog.csdn.net/c_kite/article/details/77860103

JavaScript--call(),apply()再次理解

对于call(),和apply()的作用对于大家已经不是什么陌生的东西了,他们是改变this指向。function add (a,b) { console.log(a+b) } function ...
  • zcy_csdn123
  • zcy_csdn123
  • 2017-12-19 11:52:18
  • 38

call和apply的用法以及apply的一些妙用

简要介绍了apply和call的作用及一些巧妙用法。
  • steven_zj
  • steven_zj
  • 2016-11-07 21:58:47
  • 949

JS中的call()方法和apply()方法用法总结

JacvaScript中的call()方法和apply()方法, 1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2. 相同点:这两个方法的作用是一样的。都是在特定的...
  • ganyingxie123456
  • ganyingxie123456
  • 2017-04-27 15:14:48
  • 42002

js中call与apply的用法小结

js中call与apply的用法小结 本篇文章主要是对js中call与apply的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 前天去面试,有个gg问了一些j...
  • taoerchun
  • taoerchun
  • 2016-01-06 21:25:11
  • 1749

apply的几种用法

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性. Function.apply(obj,args)方法能接收两个参数 obj:这个对象将代替Function类里this对象 a...
  • dabaxy
  • dabaxy
  • 2017-06-02 09:10:27
  • 123

scala apply()方法简单用法

apply方法类似于类的初始化方法,在遇到Object(参数1,参数2,......,参数n)时就会自动调用apply()方法。 object Test { def main(args:...
  • u013063153
  • u013063153
  • 2017-01-08 12:07:43
  • 280

T-SQL中的APPLY用法(半翻译)

本文接上文:T-SQL 中的CROSS JOIN用法(半翻译) 同样可用于微软认证70-461: Querying Microsoft SQL Server 2012考试的学习中。 ---------...
  • DBA_Huangzj
  • DBA_Huangzj
  • 2015-09-18 14:38:33
  • 5660

apply,call,bind总结用法

首先,作为一个初入js的初学者,刚碰到这几个函数使用的时候都懵逼了,不过后来慢慢学习例子,一点点理解,还是有点懂的,这个博客作为本人的首个专业博客,专门来记录一些平时需要注意的点,有错还希望能够请大家...
  • qq_31561631
  • qq_31561631
  • 2016-08-15 22:59:38
  • 217

Join 和 Apply 用法全解

在关系型数据库系统中,为了满足第三范式(3NF),需要将满足“传递依赖”的表分离成单独的表,通过Join 子句将相关表进行连接,Join子句共有三种类型:外连接,内连接,交叉连接;外连接分为:left...
  • guofang9410
  • guofang9410
  • 2017-04-10 11:04:02
  • 150

call和apply的用法和区别

call()与apply()区别 一、方法的定义  call方法:  语法:call(thisObj,Object) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 ...
  • Bin_Going
  • Bin_Going
  • 2017-05-17 12:28:34
  • 324
收藏助手
不良信息举报
您举报文章:JavaScript--call( )/apply( )用法
举报原因:
原因补充:

(最多只允许输入30个字)