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
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由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); }
完成!