JavaScript函数
一、函数和方法
JavaScript中定义函数有两种方法:
function hanshu(){
alert("hello");
}
var hs = function (x){ //通过变量定义一个函数
alert(x);
};
hs("hello");
在JavaScript中允许传入任意个参数而不影响调用。
Arguments关键字,只在函数内部有效,指向传入函数的参数,类似一个数组,但不是数组;可以用它判断传入的参数个数。
function test(x) {
alert(x); // 10
for (var i=0; i<arguments.length; i++) {
alert(arguments[i]); // 会依次输出10, 20, 30
}
}
test( 10,20, 30);
rest参数获取多出的参数;
function fun1(...rest) {
alert('多出参数:'+rest+'参数个数:'+rest.length);
}
fun1(); // 输出多出的参数(一个数组)和参数个数
fun1(5); //多出参数:5 参数个数:1
fun1(5, 6, 7);
在JavaScript中,会把函数中的申明提前,但是赋值不会提前。函数内外有重名变量,函数会屏蔽外部变量,就是说重名时在函数内部的申明有效(只是在这个函数体中)。
全局变量,实际上函数体也是一个全局变量。
局部变量,函数体内部的申明。
名字空间:
var MYAPP = {};//申明一个名字空间
//添加变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
// 添加函数:
MYAPP.foo = function () {
return 'foo';
};
const代替var定义一个常量,还有let,定义一个局部变量
方法,在一个对象中绑定函数,称为这个对象的方法(两种写法):
var xiaoming = {
name: '小明',
birth: 1995,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
alert(xiaoming.age()); //现在年龄
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1995,
age: getAge
};
alert(xiaoming.age());
//getAge(); //函数this指向window的,会返回NaN
//getAge.apply(xiaoming, []); //this指向xiaoming, 参数为空
用
var that = this;
,你就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。
另一个与apply()类似的方法是call(),唯一区别是:
apply()把参数打包成Array再传入;
call()把参数按顺序传入。
比如调用Math.max(3,4,5),分别用apply()和call()实现如下:
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
二、Array的几个方法
map()
array.map(hanshu);//则函数hanshu()对数组的每个value操作过一遍hanshu()
reduce()
arr.reduce(function (x, y) {
return x + y;
}); // reduce中必须传入两个参数,把结果继续和序列的下一个元素做累积计算
filter()
把传入的函数依次作用于每个元素,然后根据返回值是true
还是false
决定保留还是丢弃该元素。
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
使用回调函数,element是指向当前元素,index指向当前元素索引,self'指向它本身的,可以用filter()除去重复的数
arr.filter(function (element, index, self) {
return self.indexOf(element) === index;
});
sort()
方法的默认排序规则(字符串根据ASCII码进行排序),也可以自定义排序。
通常规定,对于两个元素x
和y
,如果认为x < y
,则返回-1
,如果认为x == y
,则返回0
,如果认为x > y
,则返回1
。
['Google', 'Apple', 'Microsoft'].sort(); // ['Apple', 'Google', 'Microsoft'];按照ascll码排序
//自己定义排序规则,
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1; //返回-1,则位置不变
}
if (x > y) {
return 1; //返回1,xy交换位置
}
return 0;
}); //arr=[1, 2, 10, 20] sort()是直接对数组进行修改的
sort()是直接对array进行修改的,而不是返回一个新的数组。三、闭包
一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。如上面的几个高阶函数。
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。不是返回结果,而是返回一个函数。
function _sum() {
var sum = function (){
var x;
return x;
};
return sum;
}
var f = _sum();
f();
alert(f);//返回function (){ var x; return x;};
_sum
返回函数sum
时,相关参数和变量都保存在sum中,形成一个闭包,每次调用都是返回一个新的闭包。
//返回的闭包是一个函数,所以要再次调用这个闭包才能实现它
var f = _sum();
f();
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量;因为闭包中函数不是立即执行的。
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr; //返回function(){return i*i;}
}
方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。
arr.push((function (n) {
return function () {
return n * n;
}
})(i)); //最后返回的是(function (n){return function(){ return n*n;}})(i)把i绑定了
JavaScript完成一个计数器:(以下两种实现是一样的)可以再返回的function中用变化的数,但不能用在外边
function create_counter(initial) {
var x = initial || 0;
var cc=function () {
alert(x);
x += 1;
return x;
};
return cc;
}
var c1 = create_counter();
c1();
c1();
c1();
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;//对应对象中key(inc)的value(x)
}
}
}
var c1 = create_counter();
c1.inc();//1 第一次调用返回一个
c1.inc();//2
c1.inc();//3
四、箭头函数
第一种,只含有一个一个表达式:
/*x => x * x
(x,y)=>x*x//两个参数
x =>({x:y})//返回一个对象
*/
//等价于上面个第一条语句
function (x) {
return x * x;
}
第二种,包含多条语句
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
this
在箭头函数中已经按照词法作用域绑定了,用call()
或者apply()
调用箭头函数时,无法对this
进行绑定,即传入的第一个参数被忽略:
var obj = {
birth: 1990,
getAge: function (year) {
var b = this.birth; // 1990
var fn = (y) => y - this.birth; // this.birth仍是1990
return fn.call({birth:2000}, year);
}
};
obj.getAge(2015);
五、generator
generator由function*
定义(注意多出的*
号),并且,除了return
语句,还可以用yield
返回多次。就是一个可以多次返回的函数,例如在一个数组中,不用返回整个数组就能获取到多个需要的数。
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
//调用
var f=foo();//创建一个generator对象
f.next();//获取返回的数
f.next();
//第二种调用迭代循环fib
for (var x of fib()) {
console.log(x);
}
完成!