ES6 第三章 函数
- 引言
函数无疑是任何编程语言中非常重要的一部分,函数的参数的使用是大多数前端程序员需要攻克的一个难题,因为js可以接收任意数量的参数,而无视函数声明处的参数数量
2. ES6之前如何使用
- 创建带参数默认值的函数
function makeRequest(url, timeout, callback) {
timeout = timeout || 2000;
callback = callback || function() {}
//函数的剩余部分
}
- ES6出现支持默认值的初始化
function makeRequest(url, timeout = 2000, callback = function() {}) {
//函数剩余部分
}
//使用实例1
makeRequest("/foo")
//使用实例2
makeRequest("/foo", 500)
//使用实例3
makeRequest("/foo", 500, function(body) {
something(body)
})
3. 参数arguments对象
- ES5非严格模式下
//非严格模式下,参数如果没有被初始化,arguments对象总是会被更新以反应出具体的参数的变化,因此当first与second变量被赋予新值的时候,argument也被相应的更新了,使得这里所有的 === 比较的结果都为true
function mixArgs(first, second) {
console.log(first === arguments[0]) //true
console.log(second === arguments[1]) //true
first = "c"
second = "d"
console.log(first === arguments[0]) //true
console.log(second === arguments[1]) //true
}
//非严格模式下
function mixArgs(first, second = "b") {
//arguments.length = 1
console.log(first === arguments[0]) //true
console.log(second === arguments[1]) //false
first = "c"
second = "d"
console.log(first === arguments[0]) //false
console.log(second === arguments[1]) //false
}
- ES5严格模式
//严格模式下,参数如果没有被初始化,当first与second变量被赋予新值的时候,argument不会被相应的更新
function mixArgs(first, second) {
console.log(first === arguments[0]) //true
console.log(second === arguments[1]) //true
first = "c"
second = "d"
console.log(first === arguments[0]) //false
console.log(second === arguments[1]) //false
}
//严格模式下
function mixArgs(first, second = "b") {
//arguments.length = 1
console.log(first === arguments[0]) //true
console.log(second === arguments[1]) //false
first = "c"
second = "d"
console.log(first === arguments[0]) //false
console.log(second === arguments[1]) //false
}
- 参数默认值表达式
//example1
function getValue() {
return 5;
}
function add(first, second = getValue()){ //注意是getValue() 不是getValue
return first + second;
}
console.log(add(1,2)) //3
console.log(add(1)) //6
//example2
let value = 5
function getValue() {
return value++
}
function add(first, second = getValue()) {
return first + second
}
console.log(add(1, 1)) //2
console.log(add(1)) //6
console.log(add(1)) //7
//example3
function getValue(value) {
return value + 5
}
function add(first, second = getValue(first)) {
return first + second
}
console.log(add(1,2)) //3
console.log(add(1)) //7
//example4 参数同let定义的变量一样,未被声明之前不能被使用
function add(first = second, second) {
return first + second
}
console.log(add(1, 1))
console.log(add(undefined, 1)) //2
//相当于定义 let first = 1,second = 1
console.log(add(undefined, 1)) //error
//相当于定义 let first = second, second = 1
4. 如何使用不具名参数
- ES6之前需要这样写
function pick(object) {
let result = Object.create(null);
for(let i = 1, len = arguments.length; i < len; i++) {
result[arguments[i]] = object[arguments[i]];
}
return result;
}
let book = {
title: "dongmei",
author: "Mr",
year: 2018
}
let bookData = pick(book, "author", "year", "title")
console.log(bookData) //{ author: 'Mr', year: 2018, title: 'dongmei' }
- ES6的写法
function pick(object, ...keys) {
let result = Object.create(null);
for(let i = 1, len = keys.length; i < len; i++) {
result[keys[i]] = object[keys[i]];
}
return result;
}
let book = {
title: "dongmei",
author: "Mr",
year: 2018
}
let bookData = pick(book, "author", "year", "title")
console.log(bookData) //{ author: 'Mr', year: 2018, title: 'dongmei' }
- ES6中如何使用arguments
function checkArgs(...args) {
console.log(args.length)
console.log(arguments.length)
console.log(args[0], arguments[0])
console.log(args[1], arguments[1])
}
checkArgs("a", "b") // 2 2 a a b b
5. 函数构造器的能力被增强 (看实例体会掌握)
//example1
var add = new Function("first", "second", "return first + second")
console.log(add(1, 1)) //2
//exampke2
var add = new Function("first", "second = first",
"return first + second")
console.log(add(1, 1)) //2
console.log(add(1)) //2
//example3
var pickFirst = new Function("...args", "return args[0]")
console.log(pickFirst(1, 2)) //1
7. 扩展运算符
首先你要明确针对的对象是接收参数的运算function,这时参数可以是任意数量的,比求数组中的最大值
let values = [-25, -50, -75, 100]
console.log(Math.max(...values)) //100
8. ES6新增名称属性 (所有函数都有一个name属性)
- 使用实例
//example1
function f2() {
//...
}
var f1 = function() {
//...
}
console.log(f1.name) //f1
console.log(f2.name) //f2
- 名称属性的特殊情况
var dosomething = function f1() {
//...
}
var person = {
get firstName() {
return "ma"
},
sayName:function() {
console.log(this.name)
}
}
console.log(dosomething.name) //f1
console.log(person.sayname.name) //sayname
var descriptor = Object.getOwnPropertyDescriptor(person, "firstname);
console.log(descriptor.get.name) //"get firstName"
//person.firstName实际上是一个getter函数,因此它的名称是"get firstName",已表明它的特征,同样,setter函数也会有set前缀,getter和setter函数都必须通过Object.getOwnPropertyDescriptor()来检索,使用bind建立的函数前面带bound
9. 箭头函数(重点)
- 引言:正如其名一样,用一个箭头=>就表示这个变量就是一个函数
let reflect = value => value
//等效于
let reflect = function(value) {
return value
}
- 特殊点
- 没有this、super、arguments,也没有new.target
- 不能被使用new调用,因其没有[[Construct]]方法
- 没有原型,也就是没有prototype
- 不能更改this:this的值在函数内部不能被修改,在函数的整个生命周期内其值会保持不变
- 没有arguments对象
- 不允许重复的具名函数
- 使用——创建立即调用函数表达式
let person = ((name) => {
return {
getName:function() {
return name;
}
}
})("madongmei")
console.log(person.getName()) //Nicholas
- 没有this绑定
一般this都指向了调用当前函数的那一级