3

In the interview last year, three of the five interviewers asked this question. It can be seen that this is a common interview question. I forgot how I answered it. I want to say now: Arrow function has no this binding, its this points to the parent scope

Sure enough, there is a reason for the memory failure, because there is no writing article, no understanding to really understand it

What is the real answer?

Ruan Yifeng version :

  • Arrow functions do not have their own this object, the this in the function body is the object where it is defined rather than the object where it is used
  • Cannot be used as a constructor, that is, cannot use the new command on an arrow function, otherwise an error will be thrown
  • You cannot use the arguments object, which does not exist in the function body. If you want to use it, you can use the rest parameter instead
  • The yield command cannot be used, so arrow functions cannot be used as Generator functions
  • When returning an object, you must put parentheses around the object

Nicholas version :

  • There are no this, super, arguments and new.target bindings. The values of this, super, arguments and new.target are determined by the nearest scope that does not contain an arrow function
  • Cannot be called by new, there is no [[Construct]] method inside the arrow function, so it cannot be used as a constructor, and calling the arrow function with new will throw an error
  • Without a prototype, since you can't call an arrow function with new, there's no reason for a prototype to exist. Arrow functions have no prototype property
  • This cannot be changed, and the value of this cannot be modified inside the function. The value of this is immutable throughout the life of the function
  • There is no arguments object, since arrow functions don't have arguments bound, you must rely on named or rest arguments to access the function's arguments
  • Duplicate named parameters are not allowed
Nicholas is the author of "In-depth Understanding of ES6", Ruan Yifeng will not explain

Combined, the difference between arrow functions and ordinary functions is that:

  • It can't be considered a constructor because it can't be new, and the reason it can't be new is that arrow functions don't have a [[Construct]] method inside. And because it cannot be new, there is no prototype
  • It does not have its own this, its this is determined by the object in which it is defined rather than the object in which it is used
  • It also has no arguments object
  • Cannot use yield command, cannot be used as generator function

Let's talk about these four points in turn

where does new come from

First review what new calls the constructor will do

  1. Create a new object in memory
  2. The [[prototype]] property inside this new object is assigned the prototype property of the constructor
  3. This inside the constructor is assigned the new object (this points to the new object)
  4. Execute the code inside the constructor (add properties to the new object)
  5. If the constructor returns a non-null object, return that object; otherwise, return the new object just created

We can handwrite a new

 function new2(Constructor, ...args) {
    var obj = Object.create(null);
    obj.__proto__ = Constructor.prototype;
    var result = Constructor.apply(obj, ...args)
    return typeof result === 'object' ? result : obj
}

After reviewing new, look back and see why you can't call new

There are two internal methods inside a JavaScript function: [[Call]] and [[Construct]]

  • Execute the [[Call]] method when calling directly, and execute the function body directly
  • When new is called, the [[Construct]] method is executed to create an instance object

Arrow functions were originally designed to be a shorter function without the [[Construct]] method. Specifically , arrow functions that 99.9% of people don't know cannot be used as the secret of constructors . Many English materials are extracted to support this fact.

We can say that because it doesn't have the [[Construct]] internal method, it can't be new. And because it cannot be new, it also has no prototype

The understanding of prototype can be seen here: prototype

this who called you

This in JavaScript is a lexical scope, which has nothing to do with where you define it, but where you call it, so there will be all kinds of this "demon" problems, there are 4 ways to change this

  • Called as an object method
  • call as function
  • Called as a constructor
  • Invoke with apply or call

But the arrow function does not have its own this object, the internal this is the this in the upper scope when it is defined. That is to say, the this pointer inside the arrow function is fixed

arguments old-generation array-like

arguments is an array-like object corresponding to the arguments passed to the function. The arguments object identifies the local variables available to all (non-arrow) functions. It can be said that as long as it is a (non-arrow) function, it has its own arguments, which represent all the parameters passed to the function.

What is an array-like object

The so-called array-like object refers to an object that can access elements through the index property and has a length property

 var arrLike = {
    0: 'name',
    1: 'age',
    length: 2
}

Arrow functions do not

what is yield

Before talking about yield, let's understand generators

Generators are an extremely flexible construct added to ES6, with the ability to pause and resume code execution within a function block.

The form of a generator is a function, and an asterisk (*) preceding the function name indicates that it is a generator. Generators can be defined wherever a (non-arrow) function can be defined

 // 生成器函数声明
function* generatorFn() {}

// 生成器函数表达式
let generatorFn = function* () {}

// 作为对象字面量方法的生成器函数
let foo = {
    * generatorFn() {}
}

// 作为类实例方法的生成器函数
class Foo {
    * generatorFn() {}
}

// 作为类静态方法的生成器函数
class Bar {
    static * generatorFn() {}
}

Asterisks identifying generator functions are not affected by spaces around them

The yield keyword allows the generator to stop and start executing, and is where the generator is most useful. Generator functions execute normally until the yield keyword is encountered. When this keyword is encountered, execution stops and the state of the function scope is preserved. A generator function that stops execution can only resume execution by calling the next() method on the generator object

 // umi 项目中请求接口时的例子
*fetchData({ payload }, { call, put }) {
    const resData = yield call(fetchApi, payload);
    if (resData.code === 'OK') {
        yield put({
            type: 'save',
            payload: {
                data: resData,
            },
        });
    } else {
        Toast.show(resData.resultMsg);
    }
},

The yield keyword cannot be used because arrow functions cannot be used to define generator functions

mock interview

Interviewer: Do you know ES6?

Interviewee: Well, it has always been useful in the project

Interviewer: Tell me which new features of ES6 you usually use

Interviewee: e.g. arrow functions, let, const, template strings, spread operator, Promise...

Interviewer: Hmm, what's the difference between arrow functions and normal functions?

Interviewer: Arrow functions cannot be new, have no arguments, its this is related to where it is defined, it cannot use the yield command, and the object must be returned with parentheses outside the object

Interviewer: Why can't arrow functions be new

Interviewer: Because the arrow function does not have the [[Construct]] method, when new, JavaScript will call the [[Construct]] method internally. Because the arrow function does not have it, an error will be reported when new. Of course, arrow functions also have no prototype because they cannot be new.

Interviewer: You just said that there are no arguments, briefly introduce it

Interviewee: It is a collection of all parameters, each (non-arrow) function has its own arguments, and its structure is an array-like object

Interviewer: What is an array-like object

Interviewee: An object that can access elements by index and has a length property...

Interviewer: I ask other

References

This article participated in the SegmentFault Sifu essay "How to "anti-kill" the interviewer?" , you are welcome to join.

山头人汉波
394 声望555 粉丝