1.返回值:当函数中没有return时,其函数执行完成也会返回结果,但结果为undefined。
2.函数表达式、声明:var fnName = function(){...}; 与function(){...},函数表达式与匿名函数。匿名函数也是一种函数表达式。function fnName(){...};函数声明,具有函数声明提升的效果,变成一个全局变量。类似于变量的声明,类似‘a =1’,变为一个全局变量,没有var关键字。
3.传参:允许传入任意个参,比定义的多或者少都可以。JavaScript中有一个关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数,也就是说即使不传入参数,也可以拿。类似于一个array但却又不是一个array。
function abs(){
if(arguments.length ===0){
return 0;
}
}
arguments最常用于判断传入参数的个数。
4.变量作用域:
函数内声明的变量相互独立,互不影响。内部可以使用外部变量,外部不能使用内部变量。当内、外部变量重名的时候,JavaScript会从‘内’向‘外’查找,内部函数的变量将‘屏蔽’外部函数的变量。
“变量提升”,通常为了应对JavaScript这一特性,我们会用var声明函数内部用到的所有变量。
全局作用域:不在任何函数内声明的变量就具有“全局作用域”,JavaScript有一个默认全局对象window,(实质)“全局作用域”的变量实际上被绑到了window属性上。因此,直接访问全局变量x,与window.x是完全一样的。实际上常用的alert函数也是window的一个变量。
JavaScript实际上只有一个全局作用域,任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续向上查找,最终在全局作用域中也没找到,就会报ReferenceError错误。
注意:我们在for循环等语句块中是无法定义具有局部作用域的变量的,为了实现块级作用域,ES6引入了let和const关键字。
5.解构赋值:
ES6中,引入解构赋值,可以直接对多个变量直接赋值。var ['x', 'y','z'] = ['html', 'css' , 'js'],在解构赋值的时候要注意数组的嵌套层次和位置,需要保持一致性。当从一个对象中获取某个属性时,也可以使用解构赋值的方式,便于快速获取对象的指定属性,当属性不存在时,被赋值为undefined。
注意:如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误。
var x,y
{x,y} = {name:'小明',x:100,y:200} //报错
({x,y} = {name:'小明',x:100,y:200}) //正确,这是因为JS把开头的‘{’当成了块处理,=不再合法
6.方法
绑定到对象上的函数称为方法,通常在对象方法中使用this关键字调用对象属性,this指向当前对象, 当在外部调用对象方法时,一般都会出错,这时的解决办法为,用that捕获this。
7.高阶函数
map:array的map函数用于传入我们的函数,返回一个处理后的array。把array的所有数字转换为字符串
var arr = [1,2,3]
arr.map(String);
reduce:对于传入reduce中的函数,必须向其传入两个参数,这两个参数最终从列表的第一个取,把结果和序列的下一个元素做累积计算,返回最终结果。
[x1 , x2 , x3 ].reduce(f) = f(f(x1 , x2),x3)
var x =[1,3,7]
x.reduce(function(x,y){
return x+y;
})
上例为返回列表元素和,同时还可以求积等。
filter:对array中的每个数用传入的函数过滤,返回剩余数。另外filter的回调函数还会返回元素的位置,和数组本身,但通常我们都没有使用。filter技巧,利用filter函数可以巧妙地去除array中重复的元素。
var arr = [1,2,3]
var x = arr.filter(function(element,index,self){
....
return ...;
});
sort:排序函数,默认排序方式是将array中的所有元素先转换为字符串,再进行排序,这是很不靠谱的。因为sort是个高阶函数,因此可以将自定义的排序函数(需要传入两个参数)传入sort,对数组进行排序。
提示:sort方法会直接对当前array对象进行修改,并返回当前对象。
var a = [1,2,3];
var b = a.sort();
a === b; //true
8.闭包
高阶函数除了接收函数为参数外,还可以将函数作为结果返回。含义:内部函数可以引用外部函数的参数和局部变量,当外部函数返回内部函数时,相关参数和变量都被保存在返回的函数中,这种就被称为闭包函数。
function lazy_sum(arr){
var sum = function(){
return arr.reduce(function(x,y){
return x+y;
});
}
return sum;
}
var f =lazy_sum([1,2,3]); //return sum
f(); //6
另外,每当调用一次闭包函数,都会返回一个新的函数对象,对每个函数对象的调用互不影响。
注意:返回闭包函数的关键在于,不要引用任何循环变量,或者后续会发生变化的变量。如果引用到循环中的变量,每次循环它里面的变量都会被重新赋值,直到最后多次执行该函数的时候,发现结果一样,而不是循环的结果。
function count(){
var arr = []
for(var i=1; i<=3; i++){
arr.push(function(){
return i*i;
});
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
f1(); //16
f2(); //16
闭包函数的最大作用是,在没有class机制的情况下,封装一个私有变量。例如,写一个计数器:
function create_counter(initial_num){
var x = initial||0;
return{
inc:function(){
x+=1;
return x;
}
}
}
//此例中外部无法访问到内部变量x
9.箭头函数(Arrow Function)
//两个参数
(x,y)=>x+y;
//无参
()=>3.14;
//可变参
(x,y...rest)=>{
var i ,sum = x+y;
for(i=0; i<rest.length; i++){
sum+=rest[i];
}
return sum;
}
如果要返回一个对象,必须这么写,x=>({foo : x}),这是为了防止语义错误,在外面添加一个括号。