返回新对象
function myNew() { // 1.新建一个空对象 let obj = {} // 2.获得构造函数 let con = arguments.__proto__.constructor // 3.链接原型 obj.__proto__ = con.prototype // 4.绑定this,执行构造函数 let res = con.apply(obj, arguments) // 5.返回新对象 return typeof res === 'object' ? res : obj }因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会变,并且箭头函数没有原型prototype,没法让他的实例的__proto__属性指向,所以箭头函数也就无法作为构造函数,否则用new调用时会报错!
没有new.targetnew是从构造函数生成实例对象的命令。ES6 为new命令引入了一个new.target属性,这个属性一般用在构造函数中,返回new调用的那个构造函数。如果构造函数不是通过new命令或Reflect.construct()调用的,new.target会返回undefined,所以这个属性可以用来确定构造函数是怎么调用的。
function fn(name) { console.log('fn:',new.target) } fn('nanjiu') // undefined new fn('nanjiu') /* fn: ƒ fn(name) { console.log('fn:',new.target) } */ let fn2 = (name) => { console.log('fn2',new.target) } fn2('nan') // 报错 Uncaught SyntaxError: new.target expression is not allowed here⚠️注意:
new.target属性一般用在构造函数中,返回new调用的那个构造函数
箭头函数的this指向全局对象,在箭头函数中使用new.target会报错
箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用
箭头函数没有自己的arguments 箭头函数处于全局作用域中,则没有arguments let fn = name => { console.log(arguments) } let fn2 = function(name) { console.log(arguments) } fn2() // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ] fn() // 报错 Uncaught ReferenceError: arguments is not defined还是用这两个函数来比较,普通函数能够打印出arguments,箭头函数使用arguments则会报错,因为箭头函数自身是没有arguments的,然后它会往上层作用域中去查找arguments,由于全局作用域中并没有定义arguments,所以会报错。
箭头函数处于普通函数的函数作用域中,arguments则是上层普通函数的arguments let fn2 = function(name) { console.log('fn2:',arguments) let fn = name => { console.log('fn:',arguments) } fn() } fn2('nanjiu')这里两个函数打印的arguments相同,都是fn2函数的arguments
可以使用rest参数代替ES6 引入 rest 参数,用于获取函数不定数量的参数数组,这个API是用来替代arguments的,形式为...变量名,rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
let fn3 = (a,...arr) => { console.log(a,arr) //1, [2,3,4,5,6] } fn3(1,2,3,4,5,6)上面就是rest参数的基本用法,需要⚠️注意的是:
rest参数只能作为函数的最后一个参数
// 报错 function f(a, ...b, c) { // ... }函数的length属性,不包括rest参数
rest参数与arguments的比较:
箭头函数和普通函数都可以使用rest参数,而arguments只能普通函数使用
接受参数rest比arguments更加灵活
rest参数是一个真正的数组,而arguments是一个类数组对象,不能直接使用数组方法
箭头函数不能重复函数参数名称 function fn(name,name) { console.log('fn2:',name) } let fn2 = (name,name) => { console.log('fn',name) } fn('nan','jiu') // 'jiu' fn2('nan','jiu') // 报错 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。这个可能是由于历史原因哈,TC39 在 2013 年和 2016 年分别讨论过两次,从*()、*=>、=*>、=>* 中选出了=>*,勉强进入了 stage 1。而且因为有了异步生成器(async generator),所以还得同时考虑异步箭头生成器(async arrow generator)的东西,之前生成器 99.999% 的用途都是拿它来实现异步编程,并不是真的需要生成器本来的用途,自从有了 async/await,generator生成器越来越没人用了。猜测可能是因为这个原因添加一个使用频率不高的语法,给规范带来较大的复杂度可能不值当。
箭头函数不适用场景 对象方法,且方法中使用了this var name = '南玖' var person = { name: 'nanjiu', say: function() { console.log('say:',this.name) }, say2: () => { console.log('say2:',this.name) } } person.say() // say: nanjiu person.say2() //say2: 南玖