es6函数篇

419 阅读5分钟

《深入理解ES6》之知识点记录

1,函数形参的默认值

function fn(url,timeout=2000,callback){}
  • 解释:这里设置了第二个参数为2000,在这种情况先,不为第二个参数传入值或者主动为第二个参数传入undefined时,才会使用timeout的默认值
  • 错误:之前会直接fn('/demo',,callback){}利用逗号的形式隔开,让其使用默认值,导致报错,即不能如此,而是要传入undefined

2,默认参数值对arguments对象的影响

//es5非严格模式
function fn(a){
	console.log(arguments[0]===a)//true
 	a = 1;
   	console.log(arguments[0]===a)//true
}
fn(2,2)

//es5严格模式
function fn(a){
	"use strict"
	console.log(arguments[0]===a)//true
 	a = 1;
   	console.log(arguments[0]===a)//false
}
fn(2)
//es6
function fn(a,b=2) {
	console.log(arguments.length)//1
    console.log(a===arguments[0])//true
    console.log(b===arguments[1])//false
    a = 1;
    console.log(a===arguments[0])//false
}
fn(1);//使用默认参数

function fn(a,b=2) {
	console.log(arguments.length)//2
    console.log(a===arguments[0])//true
    console.log(b===arguments[1])//true
    a = 1;
    console.log(a===arguments[0])//false
}
fn(1,2);//使用命名参数
  • es5非严格模式下:命名参数的变化会同步更新到arguments对象中
  • es5严格模式下:命名参数的变化不会同步更新到arguments对象中
  • es6使用默认参数下:arguments对象的行为同es5严格模式下一致;默认参数值存在使得arguments对象保持与命名参数分离

3,默认参数表达式

function getValue(){
	return 1
}
function fn(a,b=getValue()){
	return a+b
};
fn(1);//2
  • 解释:b的默认参数为getValue方法执行后的返回值
function getValue(){
	return 1
}
function fn(a,b=a){
	return a+b
};
fn(1);//2
  • 解释:默认参数是在函数调用时求值,所以可以使用先定义的参数作为后定义参数的默认值

4,不定参数

在函数的命名参数前添加三个点(...)就表明这是一个不定参数,该参数为一个数组

function fn(a,...b){}
fn(1,2,3,4)//则其中a为1,b为[2,3,4]

使用限制:

  • 只能有一个不定参且只能写在末尾
  • 不定参不能出现在对象字面量setter之中,之所以如此,是因为对象字面量setter的参数有且只能有一个
	var obj = {
    	set name(...val){}//会报错,不能使用不定参
    }

对arguments对象的影响:

  • 无论是否使用不定参数,arguments对象总是包含所有传入函数的参数

5,展开运算符

展开运算符可以让你指定一个数组,并通过整合后的数组来访问,使用案例:

var arr = [1,2,3,4];
//求最大值
Math.max.apply(Math,arr);
Math.max(...arr);
Math.max(...arr,0);//限制Math.max返回的最小值为0

6,函数的name属性

见代码演示:

function a(){}
var b = function(){}
var c = function d(){} 
var e = {
	f:function(){}
}
console.log(a.name);//a
console.log(b.name);//b
console.log(c.name);//d
console.log(e.f.name);//f
  • 普通的函数,name属性为声明时的函数名称
  • 匿名函数表达式的name值为被赋值为该匿名函数的变量的名称
  • 函数表达式有名字时,其名字比函数本身被复制的变量的权重要高

7,函数的多重用途

js函数里有两个不同的内部方法: [[Call]]和[[Construct]]

  • 当通过new 关键字调用函数时,执行的是[[Construct]]函数,它负责创建一个通常被称为实例的新对象,然后再执行函数体,将this绑定到实例上;具有[[Construct]]的函数被称为构造函数,并不是所有的函数都有该方法,比如箭头函数就没有。
  • 不通过new,则执行[[Call]]函数,从而直接执行代码中的函数体 如何判断函数是通过new关键字调用的呢?

元属性(new.target):

  • new.target为es6引入的元属性,是指非对象的属性,其可以提供非对象目标的补充信息(例如new)。

  • 当调用函数的[[Construct]]方法时,new.target被赋值为new 操作符的目标,通常是新创建对象实例,也就是函数体内this的构造函数

  • 当调用[[Call]]方法,则new.target的值为undefined 案例:

function Person(name) {
	if(new.target !== undefined) {
		this.name = name;
	} else {
		throw new Error(' 必须使用 new 生成实例 ');
	}
}
//  另一种写法
function Person(name) {
	if(new.target === Person) {
		this.name = name;
	} else {
		throw new Error(' 必须使用 new 生成实例 ');
	}
}
var person = new Person('狗蛋'); //  正确
var notAPerson = Person.call(person, ' 狗蛋 '); //  报错

使用: 可以利用new.target来限制类,比如,让某类不能被直接实例化使用,只能被继承使用,如下:

class Shape {
	constructor() {
		if(new.target === Shape) {
			throw new Error('不可实例化');
		}
	}
}
class Rectangle extends Shape {
	constructor(length, width) {
		super();
	}
}
var shape = new Shape(); //  报错
var rectangle = new Rectangle(10, 24); //  正确 此时new.target 为Rectangle

8,箭头函数

与传统函数的区别:

  • 没有this,super,arguments和new.target绑定;箭头函数中的this,super,arguments及new.target这些值由外围最近一层非箭头函数决定
  • 不能通过new关键字调用 箭头函数没有[[Construct]]方法;所以不能被用作构造函数,如果用new关键字调用箭头函数,会报错
  • 没有原型;由于不可以通过new关键字调用箭头函数,因而没有构建原型的需求,所以箭头函数不存在prototype这个属性
  • 不可以改变this的绑定;在函数的生命周期内始终保持一致
  • 不支持arguments对象;箭头函数没有arguments绑定,所以你只能通过命名参数和不定参数两种形式访问参数,但是若箭头函数有外围函数,则他可以访问外围函数的arguments对象
  • 不支持重复的命名参数;无论在严格模式下,箭头函数都不支持重复的命名参数,而在传统的函数规定中,只有在严格模式下才不能有重复的命名参数。