Hello everyone, it has been a long time since I wrote an article. I have sorted out an interview question from the last interview. I hope it’s helpful.

Vue overwrites the method on the array prototype to listen for array changes, so how can it ensure that other arrays are not polluted?

After the interview

Remember your last interview:

Interviewer: How does Vue implement two-way data binding?

Me: Vue hijacked the Get set method using Object.defineProperty, via… .

Interviewer: Ok, defineProperty can’t delegate arrays you know that? Do you know how Vue implements array responsiveness?

Vue overwrites the array prototype method and triggers an update in the overwritten method

Interviewer: Rewrite the prototype approach? Doesn’t that affect all arrays? How is Vue solved?

I:…

Vue source code analysis

1. The first thing we need to know is that we created an inherited prototype object, so that no matter how we overwrite the inherited object properties, the original object will not be affected.

// Array prototype object
var arrayProto = Array.prototype;
// Inherit the array prototype object
var arrayMethods = Object.create(arrayProto);

// The name of the array method being overridden
var methodsToPatch = [
    'push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'
];

methodsToPatch.forEach(function (method) {
    
    // Cache the original method
    var original = arrayProto[method];
    
    // Overwrite the new method onto the inherited object
    // arrayMethods - Inherit objects
    def(arrayMethods, method, function mutator () {
        var args = [], len = arguments.length;
        while ( len-- ) args[ len ] = arguments[ len ];
        
		// Execute the original method
        var result = original.apply(this, args);
        var ob = this.__ob__;
        var inserted;
        debugger
        switch (method) {
            case 'push':
            case 'unshift':
                inserted = args;
                break
            case 'splice':
                inserted = args.slice(2);
                break
        }
        
        // Push, unshift, splice create new array elements
        // Add the new element item to the observation array
        if (inserted) { ob.observeArray(inserted); }
        // notify change
        ob.dep.notify();
        return result
    });
});

Copy the code

ArrayMethods (arrayMethods); arrayMethods (arrayMethods); arrayMethods (arrayMethods);

const vueArray = ['a'.'b'.'c']
vueArray.__proto__ = arrayMethods

// The push method here is actually the push of arrayMethods, not array.protype.push
vueArray.push('d')
Copy the code

3. Let’s see when Vue replaces __proto__

var Observer = function Observer (value) {
    this.value = value;
    this.dep = new Dep();
    this.vmCount = 0;
    def(value, '__ob__'.this);
    if (Array.isArray(value)) {
        if (hasProto) {
            
            // This is the place
            protoAugment(value, arrayMethods);
        } else {
            copyAugment(value, arrayMethods, arrayKeys);
        }
        this.observeArray(value);
    } else {
        this.walk(value); }};function protoAugment (target, src) {
    /* eslint-disable no-proto */
    target.__proto__ = src;
    /* eslint-enable no-proto */
}
Copy the code

When executing a new Observer(value), Vue replaces value. Proto = arrayMethods if value is an array.

At this point, you are done overriding the array prototype method.

Step to summarize

  1. Create a new object that inherits the array stereotype
  2. Overrides some of the methods in the new object
  3. Assign the new prototype object to the reactive array

Answer the questions above

“Rewrite the prototype approach? Doesn’t that affect all arrays? How does Vue work?”

A: VUE overwrites its own inherited prototype objects and only works on reactive data, not contaminate the original array prototype.

Cause to think

Here to share their own reading source code skills :(big guy can skip)

Looking at the source code with a problem is more targeted than reading the source code directly, and you can also find the spirit of constant exploration and learning in order to understand a problem. After some continuous questions and then go to find the answer in the source code, like a treasure hunt, treasure hunt process vue source code is also familiar with almost.

For example, I have not understood how computed data in VUE can be used to update variables in functions in a responsive manner and cache. With this interesting question, I have become familiar with the vUE source code again. I will not talk more about the specific process here, but I will write an article later.

When using the VUE framework, we not only need to have an in-depth understanding of the API provided by the VUE official website, but also have a general understanding of its principles. So, when is the best time to learn the relevant source code of an API? In fact, is to seize every small problem we encounter in the process of using VUE, encountered problems are not only Baidu search solutions, and need to take the problem to find our own answers in the source code.