Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 58 题:箭头函数与普通函数(function)的区别是什么?构造函数(function)可以使用 new 生成实例,那么箭头函数可以吗?为什么?
箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:
1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
4、不可以使用 new 命令,因为:
- 没有自己的 this,无法调用 call,apply。
- 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 __proto__
new 过程大致是这样的:
function newFunc(father, ...rest) {
var result = {};
result.__proto__ = father.prototype;
var result2 = father.apply(result, rest);
if (
(typeof result2 === 'object' || typeof result2 === 'function') &&
result2 !== null
) {
return result2;
}
return result;
}
引入箭头函数有两个方面的作用:更简短的函数并且不绑定this。箭头函数与普通函数不同之处有:
- 箭头函数没有 this,它会从自己的作用域链的上一层继承 this(因此无法使用 apply / call / bind 进行绑定 this 值);
- 不绑定 arguments,当在箭头函数中调用 aruguments 时同样会向作用域链中查询结果;
- 不绑定 super 和 new.target;
- 没有 prototype 属性,即指向 undefined;
- 无法使用 new 实例化对象,因为普通构造函数通过 new 实例化对象时 this 指向实例对象,而箭头函数没有 this 值,同时 箭头函数也没有 prototype。
箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:
1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
4、不可以使用 new 命令,因为:
- 没有自己的 this,无法调用 call,apply。
- 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto
new 过程大致是这样的:
function newFunc(father, ...rest) { var result = {}; result.__proto__ = father.prototype; var result2 = father.apply(result, rest); if ( (typeof result2 === 'object' || typeof result2 === 'function') && result2 !== null ) { return result2; } return result; }
"函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。" 也不能说是定义时所在的对象吧,应该是定义时所在的作用域中的 this 值,因为 JS 的静态作用域的机制,this 相当于一个普通变量会向作用域链中查询结果,同时定义时所在对象也并不等于所在对象中的 this 值。
区别:
1.箭头函数没有自己的this
属性、arguments
属性、而普通函数有,箭头函数的this指向当前函数作用域的this
。
new:
2.箭头函数没有prototype
显示原型,所以不能作为构造函数。
箭头函数带来的好处:
- 没有箭头函数的时候,函数闭包
var that = this
的事没少干,有了箭头函数,就不需要这么写了。 - 极简语法,函数式风格,写一时爽一时,一直写一直爽!
箭头函数不能通过new关键字调用原因
JavaScript
函数两个内部方法: [[Call]]
和[[Construct]]
-
直接调用时执行
[[Call]]
方法, 直接执行函数体 -
new
调用时执行[[Construct]]
方法, 创建一个实例对象blabla(如下)
function New(Ctor, ...rest) {
const o = Object.create(Ctor.prototype)
const ret = Ctor.apply(o, rest)
return ret || o
}
箭头函数并没有[[Construct]]
方法, 所以不能被用作构造函数
另外, 可以参考Proxy
中的handler.construct
方法
handler.construct()
方法用于拦截new
操作符. 为了使new
操作符在生成的Proxy
对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]
内部方法(即new target
必须是有效的)。
没有自己的this,无法指向自身。构造函数生成对象需要调用函数初始化属性。
我也来献个丑:
箭头函数是ES6的写法,与function最大的不同是this的指向问题, 箭头函数内部的this 是继承自其上一级
而function 的this是看情况指向的,一般优先级是 new > bind > obj. > window new 的本质是生成一个新对象,将对象的_proto_指向函数的prototype,再执行call 方法,最后将新对象赋给定义的对象, 而箭头函数既无自己的this,也没有prototype 所以不行。
前端新手,有错误的话请不要客气,直接指出,谢谢。
箭头函数与普通函数区别: (1)箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。例子: var person = { name: '叮当猫', sayName:function () { console.log(this.name) }, sayHi: function(){ (() => { console.log('hi') ; this.sayName() })() } } person.sayHi() // hi // 叮当猫
var person = {
name: '叮当猫',
sayName:function () {
console.log(this.name)
},
sayHi: function(){
(function(){ console.log('hi') ; this.sayName() })()
}
}
person.sayHi()
// hi
//Uncaught TypeError: this.sayName is not a function
at
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
剪头函数没有自己的 this,不能用作构造函数
箭头函数由于this的指向在它定义的时候已经确定了(它外层代码的this),并不像其他普通函数在执行的时候确定this的指向,所以在new 的时候不会改变this的指向(在new 的过程中this会变成空对象然后指向对应的地方)
let num1 = [1,2,2,1]; let num2 = [2,2];
let res = []; let obj = {}; function fn(n1,n2) { for(let i = 0;i<n1.length;i++){ if(!obj[n1[i]]){ obj[n1[i]] = 1; }else{ obj[n1[i]]++ } } for(let i = 0;i<n2.length;i++){ if(obj[n2[i]]){ res.push(n2[i]); obj[n2[i]]--; } } return res }
console.log(fn(num1,num2))
箭头函数的this是上下文的this,它会从自己作用域的上一层继承this 箭头函数自身没有arguments(但是可以向作用域链中查找arguments), 不能使用yield命令,不能做generator函数 箭头函数不可以使用new,因为箭头函数没有prototype(使用new需要把函数的prototype赋值给新对象的__proto__),没有自己的this,不能调用call和apply
- 箭头函数语法简洁多了
- 箭头函数没有自己的this,它里面的this指向函数所处的上下文,call和apply也没法改变this指向
- 箭头函数没有arguments(类数组),只能基于…arg获取传递得参数集合(数组)
箭头函数不能被 new 执行,不能用作构造函数。因为箭头函数没有prototype ,也没有自己的this,不能调用call和apply
为什么不能当Generator 函数使用
箭头函数具有以下特性:
- 没有自己的 this
- 函数不会创建自己的 this,它只会从自己的作用域链的上一层继承 this
- 通过 call 或 apply 调用不会改变 this 指向
- 箭头函数不能用作构造器,和 new一起用会抛出错误
- 所以箭头函数不适合做方法函数
- 没有自己的 arguments
- 没有自己的 super 或 new.target
- super 关键字用于访问和调用一个对象的父对象上的函数。
- new.target 属性允许你检测函数或构造方法是否是通过 new 运算符被调用的
- 箭头函数没有 prototype 属性
- yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器
- 当只有一个参数时,圆括号是可选的
- 加圆括号的函数体返回对象字面量表达式
- 支持剩余参数和默认参数
- 同样支持参数列表解构
箭头函数与普通函数(function)的区别是什么?构造函数(function)可以使用 new 生成实例,那么箭头函数可以吗?为什么
- 区别1,this指向的区别,function里的this会指向调用该函数的对象,箭头函数里的this是指向作用域里的this,本身没有this指向
- 区别2,箭头函数没有arguments
- 区别3,yield 关键字不能在箭头函数中使用
- 箭头函数不能用new生成实例,因为箭头函数没有prototype属性,而new操作有一步是要把函数的prototype属性赋值给实例的__proto__,所以不能进行new操作
箭头函数是普通函数的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:
1、函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
4、不可以使用 new 命令,因为:
- 没有自己的 this,无法调用 call,apply。
- 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto
new 过程大致是这样的:
function newFunc(father, ...rest) { var result = {}; result.__proto__ = father.prototype; var result2 = father.apply(result, rest); if ( (typeof result2 === 'object' || typeof result2 === 'function') && result2 !== null ) { return result2; } return result; }
你好,我想请问一下,后面判断result的用意是什么呢?
1)、箭头函数不同于一般函数:
(1)一般函数可以先调用后定义,箭头函数只能先定义后调用
(2)一般函数有arguments,而箭头函数没有arguments,但可以使用rest参数(剩余参数)
(3)一般函数可以当作构造函数,而箭头函数不能当作构造函数,因为箭头函数没有自己的this #### 2)、箭头函数的简写形式:
(1)、当只有一个形参时可以省略圆括号;
(2)、当函数体只一条语句并且该语句会作为返回值返回时,可以省略花括号及return关键词 箭头函数中this指向依赖于外层函数中的this指向,也就是说箭头函数中的this指向定义时所在的对象,而不绑定当前调用者
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
- 没有自己的this ,this 指向的是最近作用域内的对象
- 没有 prototype,不可以进行 new 操作,没有 super,new.taret
- 没有 arguments 对象,但是可以使用 es6 rest 操作符 获取 所有参数
- 可以简写 ,如果返回值只有一句,可以省去 '{} ' 括号
- 不可以在 yied 中使用
- 绑定this 无效 call bind apply