【面试】new原理、箭头函数和普通函数区别

文章目录

    • 1.箭头函数与普通函数的区别
      • (1)区别
        • a.外形不同
        • b.箭头函数都是匿名函数
        • c.箭头函数不能用于构造函数,不能使用[new](https://editor.csdn.net/md?not_checkout=1&articleId=120271698#3new_97)
        • d.this的指向不同
        • e.箭头函数的this指向不可变
        • f.箭头函数不绑定auguments,取而代之用rest(...)解决
        • g.箭头函数不能Generator函数,不能使用yield关键字
        • h.箭头函数不具有prototype原型对象
        • i.箭头函数不具有super
        • j.箭头函数不具有new.target
    • 2.new原理
      • (1)原理
      • (2)手写new
    • 3.箭头函数可以new吗?

上一篇关于ES6的函数扩展中,在箭头函数部分提到了箭头函数的一些注意点,涉及到了箭头函数中this的指向,不能new实例等,下面详细记录一下箭头函数和普通函数的区别,以及new原理

1.箭头函数与普通函数的区别

(1)区别

a.外形不同
// 普通函数
function fn = function() {}

// 箭头函数
let fn = () => {}
b.箭头函数都是匿名函数
  • 普通函数可以是具名函数,也可以是匿名函数;
  • 箭头函数只能是匿名函数。
// 普通函数 - 具名函数
function fn() {}
// 普通函数 - 匿名函数
const fn = function (){}
// 箭头函数 - 匿名函数
const fn = () => {}
c.箭头函数不能用于构造函数,不能使用new
  • 普通函数可以用于构造函数,使用new创建实例。
function P() {
    console.log('name')
}
const p = new P() // name
d.this的指向不同
  • 普通函数中,this指向调用它的对象。如果用作构造函数,this指向创建的实例对象
  • 箭头函数本身没有this,但它在声明时可以捕获其所在上下文的this供自己使用。也就是说箭头函数的this指向的是函数声明时所在的上下文
e.箭头函数的this指向不可变
  • call()、apply()、bind()对箭头函数没有效果。
let obj2 = {
    a: 10,
    b: function(n) {
        let f = (n) => n + this.a;
        return f(n);
    },
    c: function(n) {
        let f = (n) => n + this.a;
        let m = {
            a: 20
        };
        return f.call(m,n);
    }
};
console.log(obj2.b(1));  // 结果:11
console.log(obj2.c(1)); // 结果:11
f.箭头函数不绑定auguments,取而代之用rest(…)解决
  • 每一个普通函数调用后都有arguments对象,用来存储实际传递的参数。
// 普通函数
function A(a){
  console.log(arguments);
}
A(1,2,3,4,5,8);  //  [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]

// 箭头函数
let B = (b)=>{
  console.log(arguments);
}
B(2,92,32,32);   // Uncaught ReferenceError: arguments is not defined


let C = (...c) => {
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]
g.箭头函数不能Generator函数,不能使用yield关键字
h.箭头函数不具有prototype原型对象
var a = ()=>{
  return 1;
}

function b(){
  return 2;
}

console.log(a.prototype);  // undefined
console.log(b.prototype);   // {constructor: ƒ}
i.箭头函数不具有super
j.箭头函数不具有new.target

2.箭头函数可以new吗?
不能,因为:
1.箭头函数没有prototype属性,new内部需要调用原函数的prototype属性;
2.new内部有改变this指向的操作,但是call()、bind()、apply()对箭头函数没有作用。

2.new原理

(1)原理

  1. 创建一个新对象
  2. 使新对象的__proto__属性指向原函数的prototype
  3. 改变this指向(指向新的obj),并执行该函数,执行结果保存到result
  4. 判断函数执行有没有返回其他对象,如果有就返回其他对象result,如果没有就返回原对象obj

(2)手写new

function MyNew(fn) {
    // 创建一个新对象
    const obj = {}
    // 让新对象的隐式属性__proto__指向原函数的显示属性property
    obj.__proto__ = fn.prototype
    // 改变this指向,指向obj,保存执行结果
    const res = fn.call(obj)
    // 判断执行结果是否返回其他对象
    if (typeof res === 'function' || typeof res === 'object') {
        return res    
    }
    return obj
}

3.箭头函数可以new吗?

答:不能。 因为:

  • 1.箭头函数没有prototype属性,new内部需要调用原函数的prototype属性;
  • 2.new内部有改变this指向的操作,但是call()、bind()、apply()对箭头函数没有作用。

*面试这块的题目都是一层一层问下去的,上面的题目还可以延伸到call、apply、bind的区别,手写call,__proto__和prototype还可以延伸到原型和原型链,由原型链可以考察到instanceof原理……


你可能感兴趣的:(面试,javascript,面试)