本系列属于阮一峰老师所著的ECMAScript 6 入门学习笔记javascript
function Point(x =0,y=0){ this.x = x this.y = y } const p = new Point() p // {x:0,y:0} // 参数变量是默认声明的,因此不能用let或const再次声明 function(x = 5){ let x = 1 // error const x = 2 // error } // 使用参数默认值时,函数不能有同名参数 function foo(x,x,y=1){ // ... } // SyntaxError: Duplicate parameter name not allowed in this context // 参数默认不是传值的,而是每次都从新计算默认值表达式的值。也就是说,参数默认值时惰性求值 let x = 99 function foo(p = x + 1){ console.log(p) } foo() // 100 x=100 foo() // 101
function(x,y=5){ console.log(x,y) } foo({}) // undefined 5 foo({x: 1}) // 1 5 foo({x: 1, y: 2}) // 1 2 foo() // TypeError: Cannot read property 'x' of undefined // 若是调用foo时没提供参数,变量x和y就不会生成。经过提供函数参数的默认值,能够避免 function foo({x,y=5}={}){ console.log(x,y) } foo() // undefined 5
// 一般状况下,定义了默认值的参数,应该是函数的尾参数。若是非尾部设置默认值,实际上这个参数是无法省略的 // 例一 function(x=1,y){ return [x,y] } f() // [1, undefined] f(2) // [2, undefined]) f(, 1) // 报错 f(undefined, 1) // [1, 1] //例二 function f(x,y=5,z){ return [x,y,z] } f() // [undefined, 5, undefined] f(1) // [1, 5, undefined] f(1, ,2) // 报错 f(1, undefined, 2) // [1, 5, 2] // 上面代码中,有默认值的参数都不是尾参数。这时,没法只省略该参数,而不省略后面的参数,除非显式输入undefined,null没有这个效果
指定了默认值以后,函数的length
属性将返回没有指定默认值的参数个数。java
(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
这是由于length
属性的含义是,该函数预期传入的参数个数。某个参数指定默认值之后,预期传入的参数个数就不包括这个参数了。同理,rest 参数也不会计入length
属性。es6
(function(...args) {}).length // 0
若是设置了默认值的参数不是尾参数,那么length
属性也再也不计入后面的参数了。数组
(function (a = 0, b, c) {}).length // 0 (function (a, b = 1, c) {}).length // 1
一旦设置参数的默认值,函数进行声明初始化时,参数会造成一个单独的做用域(context)。等到初始化结束,这个做用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。浏览器
let x = 1 function f(x,y=x){ console.log(y) } f(2) // 2 let x = 1 function f(y=x){ let x = 2 console.log(y) } f() // 1 // 若此时全局变量x不存在,就会报错。若参数写成x=x造成单独做用域,会造成暂时性死区报错
若是函数的默认值是一个函数,该函数的做用域也遵照这个规则函数
let foo = 'outer' function bar(func = () => foo){ let foo = 'inner' console.log(func()) } bar() // outer
ES6引入rest参数(形式为...变量名
),用于获取函数的多余参数,这样就不须要使用arguments
对象了。rest参数搭配的变量是一个数组,改变量将多余的参数放入数组中。学习
function add(...values){ let sum = 0 for(let val of values){ sum += val } return sum } add(2,3,5) // 10 // 注意,rest参数以后不能再有其余参数,不然会报错 // 函数的length属性,不包括rest参数
从ES5开始,函数内部尅设定为严格模式。ES6作了一点修改,规定只要函数参数使用了默认值、解构赋值、或者拓展运算符,那么函数内部就不能设定为严格模式,不然会报错。this
// 报错 function doSomething(value = 070){ 'use strict' return value } // 两种方法能够规避这种限制 // 1、设定全局性的严格模式 'use strict' function doSomething(a,b=a){ // code } // 2、把函数包在一个无参数的当即执行函数里面 const doSomething = (function(){ 'use strict' return function(value = 42){ return value } }())
函数的name
属性,返回该函数的函数名。这是一个早就被浏览器支持,直到ES6才写入标准的属性rest
function foo(){} foo.name // 'foo' // 对于匿名函数,ES6的name属性会返回实际的函数名,ES5则返回空字符串 var f = function(){} // ES5 f.name // '' // ES6 f.name // 'f' // 对于具名函数,ES5和ES6的name属性都返回这个具名函数本来的名字 // Function构造函数返回的函数实例,name属性的值为anonymous (new Function).name // 'anonymous' // bind返回的函数,name属性值会加上bound前缀 function foo(){} foo.bind({}).name // 'bound foo' (function(){}).bind({}).name // 'bound '
ES6容许使用”箭头“(=>
)定义函数。code
var f = v => v //等同于 var f = function(v){ return v } // 无参数或多参数写法 var f = () => 5 var sum = (num1,num2) => num1 + num2 // 返回对象 let getTempItem = id => ({id:id,name:'Temp'}) // 只有一行语句,且不须要返回值 let fn = () => void doesNotReturn() // 与变量解构结合使用 const full = ({first,last}) => first + '' + last // 与rest参数结合 const numbers = (...nums) => nums numbers(1,2,3,4,5) // [1,2,3,4,5] const headAndTail = (head,...tail) => [head,tail] headAndTail(1,2,3,4,5) // [1,[2,3,4,5]]
使用注意点
箭头函数有几个使用注意点。
(1)函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不能够看成构造函数,也就是说,不可使用new
命令,不然会抛出一个错误。
(3)不可使用arguments
对象,该对象在函数体内不存在。若是要用,能够用 rest 参数代替。
(4)不可使用yield
命令,所以箭头函数不能用做 Generator 函数。