阮一峰的ES6---函数的扩展
一,函数参数的默认值
在ES5中,设置参数的默认值:
function (x,y){
x = x || "hello";
y = y || " world";
console.log(x+y);
}
//但是如果y赋值为false时,那么y还是为默认值
因此要先判断x和y的数据类型
function(x,y){
if(typeof x === 'undefined'){
x="hello";
}
if(typeof y === 'undefined'){
y=" world";
}
console.log(x+y);
}
ES6允许在参数的默认值直接写在参数后面
function Person (name="MGT360124", age=18){
this.name = name;
this.age = age;
}
let p = new Person();
p//{name:"MGT360124",age:18}
参数变量是默认声明的,不能用let 或者const再次声明。使用默认参数时,函数不能有同名参数;
function fn(x = 5){
let x=1;//error
const x= 2;//error
}
function fn(x,x,y){//允许
}
function fn(x,y,y=10){//出错
}
二,与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值,结合起来使用
function fn(x,y=5){
console.log(x,y);
}
fn({})//undefined 5
fn({x:1})//1 5
fn({x:1,y:2})//1 2
fn();//TypeError :cannot read property "x" of undefined
三,参数默认值的位置
function person(name,age=18,sex){
return [x,y,z];
}
person()//[undefined ,18, undefined]
person("MGT")//["MGT",18,undefined ]
person("MGT", , 'M')//error
person("MGT",undefined,"M")//["MGT",18,"M"]
四,函数的length属性
length属性的返回值,等于函数的参数个数减去指定了默认值的参数个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
五,作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context),等到初始化结束时,这个作用域就会消失,这种语法行为,在不设置参数默认值时,是不会出现的;
var x= 1;
function fn(x,y =x){
console.log(y)
}
fn(2);//2
参数y的默认值就等于变量x,调用函数时,参数形成一个单独的作用域,在这个作用域里面,默认值变量y指向第一个参数x,而不是全局变量x,所以输出的是2;
let x =1;
function fn(y =x){
let x =2;
console.log(y);
}
fn();//1
上面的代码中,函数调用时,参数y = x形成一个单独的作用域,这个作用域里面,变量x本身没有定义,所以指向外层的全局变量x,函数调用时,函数体内部的局部变量影响不到默认值的变量x;如果全局变量x不存在,那么就会报错
function fn(y=x){
let x =3;
console.log(y);
}
fn();//ReferenceError :x is not defined
六,rest参数(...变量名)
ES6引入rest参数(形式为 ...变量名),用于获取函数的多与参数,这样就不需要使用arguments对象了,rest参数搭配的搭配的变量是一个数组,该变量将多余的参数放入数组中;
function add(...values) {
let sum = 0;
for(var val of values){
}
return sum;
}
add(2,5,3);//10
add是一个求和函数,利用rest参数可以求任意数目的参数
严格模式
ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
七,name属性
函数name属性,返回该函数的函数名
function person(){}
person.name //'person'
箭头函数(=>)
var f = v => v;
//等同于
var f = function(v) {
return v;
}
如果箭头函数不需要参数或者需要多个参数,就使用一个圆括号代表参数部分。
var f = () => 5;
f()//5
//等同于
var f = function (){ return 5};
var sum = (num1,num2) =>num1+num2;
//等同于
var sum = function(num1,num2){
return num1+num1;
}
sum(1,2)//3
由于花括号{}被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上一个括号,否则会报错
let getTempItem = id =>( {id:id,name:'MGT'} )
getTempItem(360124)//{id:360124,name:"MGT"}
//等同于
let getTempItem = function(id){
return { id:id, name:"MGT" };
}
getTempItem(360124)
如果箭头函数只有一行语句,且不需要返回值:
let fun = () => void doesNotReturn();
箭头函数可以结合变量解构使用
let full = ({first,escond}) => first +" "+ second ;
//等同于
function full(person){
return person.first +" "+person.last;
}
箭头函数简化回调函数
[1,2,3].map(function(x){return x*x})
//[1,4,9]
//简化
[1,2,3].map(x=>x*x);
箭头函数的注意点
(1)函数体内的this对象,就是定义时所在的对象,而不是使用所在的对象;
(2)不可以当作构造函数,不能使用new命令
(3)不可以使用arguments对象,该对象在函数体内不存在,如果要用,可以用rest参数代替
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数
this对象的指向是可变的,但是在箭头函数中,他是固定的
funnction foo(){
setTimeout( () => {
console.log("id :", this.id);
},1000);
}
var id =21;
foo.call( { id:42} );
// id :42
setTimeoout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它真正执行要等到1000毫秒以后,如果他是普通函数,执行时this应该指向全局对象window,这时输出的是21,但是箭头函数导致this总是指向函数定义生效时所在的对象{id :42},所以输出42;
function Timer () {
this.s1 = 0;
this.s2 = 0;
setInterval( () => this.s1++,1000 );
setInterval( function () {
this.s2++;
},1000);
}
var timer = new Timer();
setTimeout( ()=> console.log("s1 : ", timer.s1),3100);
setTimeout( ()=> console.log("s2 : ", timer.s2),3100);
//s1 : 3
//s2 : 0
Timer函数内部设置了两个定时器,分别为箭头函数和普通函数,前者的this绑定定义时所在的作用域(为TImer函数),后者的this指向运行时所在的作用域(window),所以3100毫秒之后,timer.s1更新了3次,而timer.s2一次都没更新;
箭头函数可以让this指向固定化,这种特性很有利于封装回调函数;
var handler ={
id :"123456",
init :function () {
document.addEventListener("click",
event => this.doSomething(event.type), false);
},
doSomething:function (type) {
console.log('handling '+type + " for " +this.id);
}
};
this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this,正是因为他没有this,所以也就不能用作构造函数。
由于箭头函数没有自己的this,所以当然也就不能用call().apply(),bind()这些方法去改变this的指向;
共同学习,写下你的评论
评论加载中...
作者其他优质文章