写在前面
注:这个系列是本人对js学问的一些梳理,个中不少内容来自书本:Javascript高等程序设计第三版和JavaScript威望指南第六版,谢谢它们的作者和译者。有发明什么题目的,迎接留言指出。
1.函数声明和函数表达式
函数声明具有声明提早/声明提拔的特征,这一点和变量的声明特征相似,实行代码之前会先读取函数声明和变量声明,意味着能够把函数声明放在挪用它的语句背面,但变量声明一定最好不要如许,由于常陪伴undefined题目。
函数声明的函数称号和函数体都提早,而函数表达式只是变量声明提早(而变量的初始化代码仍然在本来的位置)。
2.函数挪用
组成函数主体的代码定义时并不会实行,挪用函数时才会实行,有4中体式格局挪用函数:
- 作为函数
- 作为要领
- 作为组织函数
- 经由过程call()和apply()要领间接挪用
①作为函数挪用的注重点,严厉情势下挪用上下文是undefined,所以一般不运用this关键字,②作为要领挪用的话挪用上下文就是要领地点的对象,this关键字援用着该对象。③而嵌套函数不会从挪用它的函数中继续this,假如想接见外部的this,能够用变量保留this的值。④组织函数挪用会运用新创建的对象作为挪用上下文。
3.函数的参数相干
- 可选形参
当传入的实参比函数声明时指定的形参数目要少,剩下的形参都将设置为undefined值(实参多则会自动省略)。所以在适宜的场景就能够挑选运用可选形参:
function getPropertyNames(o, /* optional */ a) {
if(a=== undefined) a=[];
for(var prop in o) a.push(prop);
return a;
}
var arr = [1,2];
//[1, 2, "x", "y"]
console.log(getPropertyNames({x:1,y:2},arr));
//["x", "y"]
console.log(getPropertyNames({x:1,y:2}));
注重点:须要将可选形参放在形参列表的末了,并在函数定义是运用解释强调形参是可选的。
- 实参对象arguments
在函数体内,标识符arguments是指向实参对象的援用,它是一个类数组对象,能够经由过程数字下标接见传入的实参值,如许函数就能够操纵恣意数目的实参:
function getMaxValue(/* ... */) {
var max = arguments[0];
for(var i=0,len=arguments.length;i<len;i++){
if(arguments[i]>max){
max = arguments[i];
}
}
return max;
}
console.log(getMaxValue(4,2,1,8,10));//10
- 将对象属性用作实参:当一个函数的形参过量(比方凌驾3个),挪用时记着实参的准确递次不容易。这时刻能够把形参写成一个对象,就没有参数递次的影响了,而且还能够在取值的时刻运用||标记设置默认值。固然,形参不多就不需如许做,效力会低一些。
- 在每一个形参左侧运用相似/*array*/的范例解释。在函数体内应当要有实参范例搜检的逻辑,在传入不法值时报错。
- 自定义函数属性:函数是一种特别的对象,所以在恰当的时刻能够给函数定义属性,比方函数须要一个“静态变量”:
//阶乘
function factorial(n) {
if(isFinite(n) && n>0 && n==Math.round(n)){
if(!(n in factorial)) factorial[n] = n * factorial(n-1);
return factorial[n];
}
else return NaN;
}
factorial[1] = 1;
console.log(factorial([5]));//120
4.作为定名空间的函数
为了不污染全局空间,经常使用定义匿名函数并立即在单个表达式中挪用的体式格局:
var extendFun = (function () {
//函数体
}());
5.call()、apply()和bind()
- call()和apply()
call()和apply()是函数的要领,经由过程挪用要领的情势来简介挪用函数,我们之前引见继续的时刻,有一个处所是借用超范例的组织函数,就是运用了call。它们的第一个实参是要挪用函数的母对象,它是挪用上下文,函数体内经由过程this援用它。
call除了第一个参数以后的参数就是要传给函数的值:
function logMsg(x,y,z) {
console.log(x+'/'+y+'/'+z);
}
//打印2/4/6
logMsg.call({},2,4,6);
而apply除了第一个参数之外,供应一个数组用于传给函数:
function logMsg(x,y,z) {
console.log(x+'/'+y+'/'+z);
}
//打印8/10/12
logMsg.apply({},[8,10,12]);
apply的数组参数能够是实在数组,也能够是类数组对象,比方能够把当前函数的arguments数组直接传入:
function logMsg(x,y,z) {
console.log(x+'/'+y+'/'+z);
}
function wantToLog(a,b,c) {
logMsg.apply({},arguments);
}
//打印1/2/3/4
wantToLog(1,2,3);
- bind()
这个要领重要作用是将函数绑定至某个对象,除了第一个实参之外,其他的实参会传入到函数内里:
function f(y,z) {
console.log("y:"+y);//y:4
console.log("z:"+z);//z:2
return this.x + y + z;
}
var g = f.bind({x:3},4);
console.log(g(2));//3+4+2=9
//这内里绑定了this和y