参数
形参(parameter):函数中定义的变量
实参(argument):运行时的函数挪用时传入的参数
上下文(context):经由过程对象来挪用函数时,这个对象就是this就是上下文;
闭包(closure):函数嵌套在函数当中
1 函数挪用的体式格局
有4种要领来挪用JavaScript函数:
作为函数
作为要领
作为组织函数
经由过程call要领和apply要领间接挪用
ES3 和非严厉情势下的ES5中,挪用上下文(this的值)是全局对象。在严厉情势下,挪用上下文则是undefined
1.1 函数挪用
语法:
functionName()
window.name = "hello";
(function () {
console.log(this); //window
})()
"use strict";
window.name = "hello";
(function () {
console.log(this); //undefined
})()
1.2 要领挪用
语法:
obj.functionName()
要领和this关键字是面向对象编程范例的中心
要领链
要领链:当要领的返回值是一个对象,这个对象还能够再挪用它的要领。这个要领挪用序列就是要领链;
1.3 组织函数挪用
没有形参的组织函数挪用都能够省略小括号
1.4 间接挪用
call要领:运用它自有的实参列表作为函数的实参;
apply要领:请求以数组的情势传入参数;
2 函数的实参和形参
2.1 可选形参
当挪用函数的时刻传入的实参比函数声明时指定的形参个数要少,剩下的形参都将是undefined;所以在定义函数的时刻应该给省略的参数赋一个默认值:
function pushArray(o, /* optional */ a) {
if (a === undefined) a = [];
// a = a || [];
for (var property in o) a.push(property);
return a;
}
var o = {
name: "Oliver",
age: 18
};
var a = ["friends"];
console.log(pushArray(o, a).toString()); //friends,name,age
2.2 实参对象
省略的实参都是undefined;多出的参数自动疏忽
别的,能够经由过程arguments来猎取过剩的参数,arguments.length取得参数个数
不定实参函数(varargs function):吸收恣意个数的实参
不定实参函数的实参个数不能为零;
ES5之前,arguments[0]和x指代同一个值;
function pushArray(a) {
console.log(a); //Array
arguments[0] = 10;
console.log(a); //Array
console.log(arguments[0]); //10
}
var a = ["friends"];
pushArray(a);
2.3 将对象属性用作实参
最好经由过程名值对的情势传入参数(传入的实参都写入一个零丁的对象当中,在挪用的时刻传入一个对象)
function outputString(obj) {
var fname = obj.firstName,
lname = obj.lastName,
age = obj.age;
console.log(`your fisrtName: ${fname}; lastName: ${lname}; age: ${age}`);
}
outputString({firstName: "Oliver", lastName: "Young", age: 18}); //your fisrtName: Oliver; lastName: Young;
3 作为值的函数
函数也是值,能够将函数赋值给变量,存储在对象的属性和数组的元素中,作为参数传入别的一个函数等
函数是对象,能够定义本身的属性
log.conter = 10;
function log () {
console.log(log.conter);
}
log(); //10
如许函数就不须要再定义一个全局变量
4作为定名空间的函数
将代码放入一个函数内,然后挪用这个函数:
差别的写法:
function log (i) {
console.log("hello" +i);
}
log(100);
(function log (i) {
console.log("hello" + i);
}(100))
(function log (i) {
console.log("hello" + i);
})(100)
小括号括起来防止JavaScript诠释器剖析为函数声明语句
5 闭包
词法作用域(lexical scoping):函数的实行依赖于变量作用域,这个作用域是在函数定义时决议的,而不是函数挪用时决议的。
闭包:函数对象能够经由过程作用域互相关联起来,函数体内部的变量都能够保存在函数作用域内。
上面的log.conter属性就能够运用包含在闭包中:
var pro = (function() {
var conter = 10;
function log(argument) {
console.log(conter++);
}
return log;
})();
pro(); //10
pro(); //11
pro(); //12
运用多个嵌套函数:
function counter () {
var num = 0;
return {
count: function () {
return num ++;
},
reset: function () {
num = 0;
}
};
}
var newCounter = counter(); //这里是新的计数器,再赋值一个变量能够获得别的一个计数器,二者不受影响
console.log(newCounter.count()); //0
console.log(newCounter.count()); //1
console.log(newCounter.count()); //2
newCounter.reset();
console.log(newCounter.count()); //0
console.log(newCounter.count()); //1
console.log(newCounter.count()); //2
6 函数属性、要领和组织函数
6.1 length属性
函数的length返回的是形参的数目;函数内部arguments.length返回的是实参的数目
function add(x, y) {
return arguments.length;
}
console.log(add.length); //2
console.log(add(1)); //1
6.2 prototype属性
6.3 call()和apply()要领
经由过程挪用要领的情势来间接挪用函数,call和apply的第一个实参是要挪用函数的母对象,它是挪用上下文。
比方,以对象o的要领的情势挪用函数f()并传入两个参数:f.call(o, 1, 2)
apply能够传入的参数能够是数组和类数组的。
6.4 bind()要领
ES5的该要领重要作用是将函数绑定至某个对象,要领返回一个新的函数,挪用这个新的函数会把绑定的函数在对象中当作要领来挪用。
function add(y) {
return this.x + y;
}
var o = {
x: 100
};
var g = add.bind(o);
console.log(g(100)); //200
柯里化(currying):除了第一个实参外,传入bind的实参也会绑定至this;
function add(x, y) {
return x + y;
}
var o = {
};
var g = add.bind(o, 100); //x是100
console.log(g(100)); //200 y是100
//上面的o对象能够去掉:
function add(x, y, z) {
return x + y + z;
}
var g = add.bind(null, 100, 100, 100); //x是100 y是100 z是100
console.log(g()); //300
//又如:
function add(y, z) {
return this.x + y + z;
}
var g = add.bind({x:100}, 100, 100); //{x是100} y是100 z是100
console.log(g()); //300
6.5 toString()要领
6.6 Function()组织函数
Function()组织函数所建立的函数并非运用此法作用域:
var scope = "global";
function constructFunction () {
var scope = "local";
return new Function("return scope");
}
console.log(constructFunction()()); //global
var scope = "global";
function constructFunction () {
var scope = "local";
return function () {
return scope
};
}
console.log(constructFunction()()); //local
6.7 可挪用的对象
7 函数式编程
7.1 运用函数处置惩罚数组
如要盘算元素的平均值:
var arr = [1,2,3,4,5];
var total = 0;
for (var i = 0; i < arr.length; i++) {
total += arr[i];
};
var result = total/arr.length;
console.log(result); //3
函数式编程作风:
var arr = [1,2,3,4,5];
function sum (a, b) {
return a + b;
}
var total = arr.reduce(sum);
var result = total/arr.length;
console.log(result); //3
7.2 高阶函数
高阶函数(higher-order function):就是操纵函数的函数,它吸收一个或多个函数作为参数,并返回一个新函数
function reverse(fun) {
return function () {
var result = fun.apply(this, arguments);
return !result;
}
}
var even = function (x) {
return x % 2 === 0;
};
var odd = reverse(even);
console.log(odd(100)); //False
console.log(even(100)); //True
7.3 不完全函数
7.4 影象
影象(memorization):部份结果在函数式编程中被缓存起来,这类缓存技能就是“影象”