函数参数
- arguments(可变参):伪数组(有 index 和 length),存的传入的参数,可以用for 遍历
- js函数可变参的写法
function test(a,b,...rest)
,rest的本质也就是一个数组 - 函数可变参(rest参数)实际是es6的新标准,es6还支持参数默认值的设置
- 函数的参数在声明的时候写不写都可以,写多少个也没有规定,底层是用数组实现的,函数声明的括号里写上形参只是为了函数内部使用的方便;函数在调用的时候要传几个实参都是可以的,反正是传几个接受几个;
- 由于 js 函数参数的以上特点,所以 js 的函数没有真正意义上的重载,同名的函数会覆盖
- 函数传参:参数的改变在函数之外是不可见的,对象属性的改变在函数之外是可见的
- 函数声明随意写在什么位置都不影响函数的调用,但是函数表达式必须写在调用之前才不会出错;
//函数表达式
var run = function (v1) {
alert(v1);
};
//函数声明
function run() {}
函数闭包
函数嵌套
匿名函数
- 作为其他函数的参数和返回值
- 作为立即执行函数使用:前面的括号的包裹不可或缺
(function () {
var x = "Hello!!";
})();
闭包概念
- 子函数有权访问父作用域的函数,即使在父函数关闭之后,闭包最大的作用是将变量私有
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
递归函数
解构赋值
- 也是ES6的一个特性
一、数组解构
二、对象解构
- 下面的代码 address 无法解构,里面的city等可以解构
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school',
address: {
city: 'Beijing',
street: 'No.1 Road',
zipcode: '100001'
}
};
var {name, address: {city, zipcode}} = person;
三、使用场景
- 解构赋值在很多时候可以大大简化代码,比如两个值的交换
- 方法参数的自动匹配,前提是方法参数接受一个对象
对象方法
- 对象的属性是一个函数
一、关于关键词this
- this 在对象内部指的就是对象本身
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
- 函数中嵌套函数的情况:最外层的函数可以直接使用
this
,这里的this
是指向的对象本身,里层的函数要使用this
的话需要通过that
进行访问,否则的话实际访问就是window
对象,使用严格的模式的话就是undefined
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var that = this; // 在方法内部一开始就捕获this
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - that.birth; // 用that而不是this
}
return getAgeFromBirth();
}
};
二、apply 和 call
- 可以通过函数本身的 apply 和 call 方法指定函数内部的 this 的指向
- apply的方法参数是包装为array传入的,call的参数是直接按位置进行匹配
Math.max.apply(null,[12,34,100,2,5])
100
Math.max.call(null,12,45,100,56,45)
100
- call和apply一个很大的作用就是实现函数的复用:
p1.fullName.apply(p2)
三、简单装饰器的实现
- 这里实现的方法调用次数的计数功能增强,好像没啥用~~~~
'use strict';
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};
高阶函数
- 高阶函数就是函数作为参数或者返回值的函数
一、map/reduce
- map函数就是把传入的参数函数作用于数组的每一个元素,然后返回
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
- reduce就是一个累积的效果,第一个参数表示上次计算结果,第二参数表示数组的下一个元素
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
- map和parseInt一起使用的陷阱?????
二、filter
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (value, index, array) {
console.log(value);
console.log(index);
console.log(array);
return true;
});
三、sort
- sort 方法排序数字要有一个比较函数
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
console.log(arr); // [1, 2, 10, 20]
四、数组的其他高阶函数
- every:判断数组中是否所有的元素都满足条件
- find:找数组中满足条件的第一个元素,返回元素,没找到返回undefined
- findindex :找数组中满足条件的第一个元素,返回索引,没找到返回-1
- forEach: 用来遍历数组不会像map一样返回一个数组
箭头函数
- 就是类似于 python 中 lambda 函数的东西,就是实现一个匿名函数
- 也是ES6中引入的新东西,为JS提供了函数式编程的支持
- 简化了函数的定义过程
一、基本用法
- 最简单的写法
x => x * x
- 最完整的写法:也就是说如果参数只有一个,函数体的代码只有一句的话,小括号和大括号都是可以省略的
(x, y, ...rest) => {
var i, sum = x + y;
for (i=0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}
- 如果返回的是一个对象
x => ({ foo: x })
二、箭头函数中的this
- 示例代码中的this完全可以正常使用了
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
}
};
obj.getAge(); // 25
三、使用细节
- 箭头功能没有自己的 this,它们不适合定义对象方法
- 箭头功能未被提升,它们必须在使用前进行定义
- 使用 const 比使用 var 更安全,因为函数表达式始终是常量值
const test12 = function(){console.log('test')}
generator
- 这个东西也是ES6中引入的,设计者借鉴了python中 generator 的思路设计了这个
一、基本概念
- 定义的方法就是在函数定义的基础上加上
*
作为标记,函数体的内部用 yield 关键字进行值的返回 - 从测试的代码可以看出,generator 的本质就是一个函数,不过是一个比较特殊的函数而已
- 调用这个特殊的方法得到的并不是返回的值而是一个generator对象,返回值需要继续调用 next 方法
- next 方法返回一个 object ,这个对象包含两个属性,done是判断这个generator 是否执行结束,true代表结束返回的value的值就是return的值,false 代表未执行结束,返回的value就是yield 返回的值
- 用 next 对 generator 进行取值要判断是否执行结束,用
for--of
进行取值的话就不需要
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}
for (var x of fib(10)) {
console.log(x); // 依次输出0, 1, 1, 2, 3, ...
}
generator 最大的优势就是可以保存变量的状态,普通函数需要依赖全局变量或者是对象的属性才能实现