默认参数:
1. 在 ES5 语法中,为函数形参指定默认值的写法:
写法一: function foo (bar) { bar = bar || 'abc'; console.log(bar) } foo('xyz') 写法二: function foo (bar) { if (typeof bar === 'undefined') { bar = 'abc'; } console.log(bar) } foo('xyz');
2. 使用 ES6 的语法为函数形参指定默认值
function post (url, data = {}, timeout = 5 * 1000) { console.log(arguments) console.log(url, data, timeout) } // post('xyz', {uname: 'zhangsan', upass: '123'}, 3000); post('xyz', null, 3000);
注意事项:
1> 除了为形参直接指定默认值以外,形参的默认值还可以是表达式,例如,timeout = 5 * 1000
2> 在预编译阶段,形参表达式不会执行,只有在调用函数,并且没有为形参传递实参的情况下才执行
不定参数:
使用剩余操作符接收剩余的实参,这些实参会被保存到一个不定参数(args)中
function foo (...args) { return args.reduce(function (previousValue, currentValue) { console.log(previousValue, currentValue) return previousValue += currentValue; }) } // 将上面的函数改成箭头函数的形式 var foo = (...args) => args.reduce((a, b) =>a += b) console.log(foo(1, 32, 34, 5, 6))
箭头函数:
// 1. 形式一: var foo = function () { return 'Hello World!'; }; // 如果形参数量为 0,则必须加上小括号。箭头后面的表达式的结果会被作为函数的返回值。 var foo = () => { return 'Hello World!'; } // 2. 形式二: var foo = function (greeting) { return greeting; } // 如果形参的数量为 1,则可以省略小括号。 var foo = greeting => { return greeting; } // 3. 形式三: var foo = function (firstName, lastName) { return firstName + ' · ' + lastName; } // 如果形参数量大于 1,则不能省略小括号。 var foo = (firstName, lastName) => { return firstName + ' · ' + lastName; } // 4. 形式四: var foo = function (a, b) { return a > b ? a : b; } // 如果函数的执行体比较简单(直接量或表达式),可以省略大括号,箭头后面的直接量或表达式会被自动作为返回值。 var foo = (a, b) => a > b ? a : b; // 5. 形式五: var foo = function (a, b) { let max = a; if (b > a) { max = b; } return max; } // 如果函数的执行体比较复杂,则不能省略大括号。 var foo = (a, b) => { let max = a; if (b > a) { max = b; } return max; } console.log(foo('赵四', '尼古拉斯'))
箭头函数没有this指定:
// 普通函数作用域中的 this 已经被绑定成 window 对象,因此当我们放问 this 时,直接在当前作用域下就能访问的到。 var foo = function () { console.log(this) return 'Hello World!'; }; // 箭头函数的作用域中没有绑定 this,因此,当我们访问 this 时,会去上一层作用域中查找 this。 var bar = () => { console.log(this) return 'Hello World!'; }; // 示例,由于 sayName 箭头函数中没有绑定 this,因此我们访问 this 时,会去全局作用域中查找。 // 查找的结果是 this 指向 window,因此输出的 name 的值是 '猪猪侠' var name = '猪猪侠'; var obj = { name: '煎饼侠', sayName: function () { // this = obj return this.name; } }; console.log(obj.sayName())
箭头函数没有arguments绑定:
// 普通函数 var foo = function (greeting) { console.log(arguments) return greeting; }; // 箭头函数中没有绑定 arguments 对象,因此下面的输入语句会报错:arguments is not defined var bar = (greeting) => { console.log(arguments) return greeting; }; console.log(foo('Hello World!')) console.log(bar('你好世界!'))
箭头函数中不能手动绑定this:
// this 指向的对象 var obj = { fullName: '沃尔玛' }; // 1. 普通函数,可以使用 call() 方法改变函数中 this 的绑定 var foo = function (greeting) { return this.fullName + '说:' + greeting; }; console.log(foo.call(obj, 'Hello World!')) // 2. 箭头函数,不能使用 call() 方法改变函数中 this 的绑定,箭头函数中不能绑定 this。 var bar = (greeting) => { return this.fullName + '说:' + greeting; }; // 下面的代码不会报错,但是也不起作用 console.log(bar.call(obj, '你好世界!'))
函数--new.target:
// 1. ECMAScript 5 中判断构造函数是否通过 new 关键字调用的写法 function Person (fullName) { if (this instanceof Person) { this.fullName = fullName; } else { return new Person(fullName); } } let student = Person('八戒') // 2. ECMASript 6 引入一个 new.target 属性,当我们使用 new 操作符调用构造函数时,new.target 属性的值为构造函数,否则为 undefined function Person (fullName) { if (typeof new.target !== 'undefined') { this.fullName = fullName; } else { throw new Error('必须通过 new 关键字来调用 Person。'); } } let student = new Person('八戒'); console.log(student) // 3. 除此之外,还可以检查 new.target 是否被某个特定构造函数所有调用。 // 例如,Person 构造函数中的 new.target 属性的值被限定为 Person function Person (fullName, age) { if (typeof new.target === Person) { this.fullName = fullName; this.age = age; } else { throw new Error('必须通过 new 关键字来调用 Person。'); } } function Dog (fullName, age) { Person.call(this, fullName, age) } let dog = new Dog('HeHe', 3) console.log(dog) // 4. 不能在函数外部使用 new.target,否则会报错 function Person () { console.log(new.target) } // 下面代码会抛出错误:new.target expression is not allowed here console.log(new.target) let student = new Person('悟净')