[Effective JavaScript 笔记]第21条:使用apply方法通过不同数量的参数调用函数
apply()方法定义
函数的apply()方法和call方法作用相同,区别在于接收的参数的方式不同。
apply()方法接收两个参数,一个是对象,一个是参数数组。
apply()作用
1、用于延长函数的作用域
示例:
var color='red';
var o={color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor();//"red"
sayColor.apply(o);//"blue"
这里通过apply()方法把函数动态绑定到了对象o上了,这时this指向o对象,得到结果"blue"。
2、对象不需要与方法有任何耦合关系
下面举个耦合的例子,看如何通过apply来解决这种耦合。
var color='red';
var o={color:'blue'};
function sayColor(){
console.log(this.color);
}
o.sayColor=sayColor;
o.sayColor();//"blue"
这里先将函数放到了对象o中,这里对象和方法就紧耦合到一起了,方法的调用必须通过对象o。
没有使用apply()和call()方法那样灵活。
重构上面代码,得到前例中的代码。
var color='red';
var o={color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor();//"red"
sayColor.apply(o);//"blue"
这里对象并没有绑定任何方法,只是在需要使用的时候,利用函数的apply或call方法来动态绑定。
对象和方法之间没有耦合在一起。这里还可以通过ES5提供的bind()方法来完成
3、实现可变参数函数传参
下面一个计算任意数量数字平均值的函数
average(1,2,3);
average(1);
average(3,1,2,3,5,6,7,8,9);
average(1,2,3,5,2,1,5,6,1,10);
average函数是一个称为可变参数或可变元函数(函数的元数是指其期望的参数个数)的例子。
当然这个函数也可以写成一个接收数组的形式。
averageOfArray([1,2,3]);
averageOfArray([1]);
averageOfArray([3,1,2,3,5,6,7,8,9]);
averageOfArray([1,2,3,5,2,1,5,6,1,10]);
使用可变参数的函数更简洁、优雅。可变参数函数具有便捷的语法,至少让调用者预先明确地知道提供了多少个参数。
如果我有这样一个数组
var scores=getAllScores();
如何使用average函数计算平均值呢?
1.可变参数函数版本。
这时就可以和apply()方法配合使用,这里因为函数并没用引用this变量,因此第一个参数我们传入一个null。代码如下:
var scores=getAllScores();
average.apply(null,scores);
2.直接参数为数组的形式
这里可以直接传入数组参数。
var scores=getAllScores();
averageOfArray(scores);
以上两种形式,个人觉得都是可以,反而第二种更简单。多知道一种方法,对于遇到别人写的函数时,可以轻松应对,不需要重构代码。这个好处反而更多。
4、实现可变参数方法的传值
示例:buffer对象包含一个可变参数的append方法,该方法添加元素到函数内部的state数组中。
var buffer={
state:[],
append:function(){
for(var i=0,n=arguments.length;i<n;i++){
this.state.push(arguments[i]);
}
}
};
这时append方法可以接受任意多个参数。
buffer.append('Hello,');
buffer.append('firtName',' ','lastName','!');
buffer.append('newLine');
形式如
buffer.append(arg1,arg2,arg3,...)
借助apply方法的this参数,我们可以指定一个可计算的数组调用append方法
buffer.append.apply(buffer,getInputStrings());
注意:这里的buffer很重要,如果传递不同的对象,则append方法将尝试修改该错误对象的state属性。
提示
- 使用apply方法指定一个可计算的参数数组来调用可变参数的函数
- 使用apply方法的第一个参数给可变参数的方法提供一个接收者
附录一
average函数
function average(){
var args=[].slice.call(arguments);
var sum=args.reduce(function(prev,cur){
return prev+cur;
});
return parseInt(sum/args.length,10);
}
averageOfArray函数
function averageOfArray(arr){
var sum=arr.reduce(function(prev,cur){
return prev+cur;
});
return parseInt(sum/arr.length,10);
}
ES5 bind()方法
例如
var color='red';
var o={color:'blue'};
function sayColor(){
console.log(this.color);
}
var oSayColor=sayColor.bind(o);
oSayColor();//"blue"
兼容低版本,参考使用下面的版本:
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
} var aArgs = [].slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP? this: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
}; if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP(); return fBound;
};
}
[Effective JavaScript 笔记]第21条:使用apply方法通过不同数量的参数调用函数的更多相关文章
- [Effective JavaScript 笔记]第50条:迭代方法优于循环
"懒"程序员才是好程序员.复制和粘贴样板代码,一但代码有错误,或代码功能修改,那么程序在修改的时候,程序员需要找到所有相同功能的代码一处处进行修改.这会使人重复发明轮子,而且在别人 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第23条:永远不要修改arguments对象
arguments对象并不是标准的Array类型的实例.arguments对象不能直接调用Array方法. arguments对象的救星call方法 使得arguments可以品尝到数组方法的美味,知 ...
- [Effective JavaScript 笔记]第22条:使用arguments创建可变参数的函数
第21条讲述使用可变参数的函数average.该函数可处理任意数量的参数并返回这些参数的平均值. 如何创建可变参数的函数 1.实现固定元数的函数 书上的版本 function averageOfArr ...
- [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法
不好的实践 函数或方法的接收者(即绑定到特殊关键字this的值)是由调用者的语法决定的.方法调用语法将方法被查找的对象绑定到this变量,(可参阅之前文章<理解函数调用.方法调用及构造函数调用之 ...
- [Effective JavaScript 笔记]第33条:使构造函数与new操作符无关
当使用函数作为一个构造函数时,程序依赖于调用者是否记得使用new操作符来调用该构造函数.注意:该函数假设接收者是一个全新的对象. 一个例子 function User(name,pwd){ this. ...
随机推荐
- 【MyEclipse 2015】 逆向破解实录系列【1】(纯研究)
声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...
- Boostrap(4)
1.按钮 <!doctype html> <html> <head> <meta charset="utf-8"> <titl ...
- LINQ浅析
在C# 3.0之前,我们对不同的数据源(数据集合.SQL 数据库.XML 文档等等)进行操作(查询.筛选.投影等等),会使用不同的操作方式. C# 3.0中提出了LINQ(Language Integ ...
- 一头扎进EasyUI2
惯例广告一发,对于初学真,真的很有用www.java1234.com,去试试吧! 一头扎进EasyUI第6讲 .日历组件 <div class="easyui-calendar&quo ...
- HOW TO REMOTELY DEBUG APPLICATION RUNNING ON TOMCAT FROM WITHIN INTELLIJ IDEA
This post would look into how to tackle and debug issues in scenarios where they only occur in produ ...
- 【BZOJ 1013】【JSOI2008】球形空间产生器sphere 高斯消元基础题
最基础的高斯消元了,然而我把j打成i连WA连跪,考场上再犯这种错误就真的得滚粗了. #include<cmath> #include<cstdio> #include<c ...
- 【BZOJ 3036】 绿豆蛙的归宿
求期望的题目(~~~water~~~) 压了下代码,压成15行hhh: 我把代码压成这么丑估计也没有人看吧: 毕竟是zky讲的一个水题,就当给博客除草了: dfs回溯时求当前节点的f,除以当前节 ...
- 读JS高级——第五章-引用类型 _记录
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Android4.4中不能发送SD卡就绪广播
当在Android上进行图片的扫描功能开发时一般会使用:sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(“file:// ...
- Spring JdbcTemplate 的使用与学习
JDBCTemplate 是SPRING 框架自带的一种对sql 语句查询的封装 ,封装非常完善,虽然与Hibernate比起来有一点麻烦,但是学号JDBCTemplate可以让我们用Spirngmv ...