Basic concept

Object.defineProperty

Object.defineProperty(..) It is used to add a new property or modify an existing property (if it is a different property) and set the features.

grammar

Object.defineProperty(obj, prop, descriptor)

var obj = {}
Object.defineProperty(obj, 'a', {
    value: 2.writable: true.configurable: true.enumerable: true.get: function() {
        return this._a
    },
    set: function(val) {
        this._a = val + 2
    }
})
obj.a / / 2
Copy the code

The property descriptor represented by the third parameter descriptor of a function has two forms: the data descriptor and the access descriptor.

Both data descriptors and access descriptors have properties such as:

  • configurable
  • enumerable

The optional attributes of the data descriptor are:

  • value
  • writable

The available key values of the access descriptor are:

  • get
  • set

Before we look at how vUE implements responsiveness, we need to know a few concepts:

  • Attribute descriptor
  • Object.defineProperty
  • [[GET]],[[PUT]]
  • Access descriptor

What is a property descriptor

Before ES5, the JS language itself did not provide a way to directly detect the properties of attributes. Starting with ES5, all attributes have attribute descriptors.

var obj = {
    m: 1
}
Object.getOwnPropertyDescriptor(obj, "m")
/ / {
// value: 1,
// writable: true,
// enumerable: true,
// configurable: true
// } 
Copy the code

This is the property descriptor, which, in addition to the number 2, contains three additional features: Writable, Enumerable, and freely configurable.

When normal objects are created, the property descriptors use the default value, which is true. Its property descriptor can also be set using Object.defineProperty.

[[GET]]

Obj. M implements the [[GET]] operation on obj (similar to function call: [[GET]]()).

The default built-in [[Get]] operation on an object first looks for an attribute with the same name in the object, and returns the value of that attribute if found. If not, a prototype chain lookup is performed

var obj = {
    m: 1
}
obj.m / / 1
Copy the code

If it can’t be found anyway, the [[Get]] operation returns undefined

[[PUT]]

The counterpart of [[Get]] is the [[PUT]] operation.

When assigning a value to a property, [[PUT]] is emitted, but the success of [[PUT]] depends on the property descriptor writable and access descriptor setter

What is an access descriptor

Defining a getter, setter, or both for a property sometimes the property is defined as an “access descriptor” (as opposed to a “data descriptor”)

In ES5, you can override default actions using getter and setter sections, but only for individual properties, not for entire objects.

  • A getter is a hidden function that is called when a property value is obtained
  • Setter is also a hidden function that is called when the property value is set
var obj = {
    get m() {
        return 2
    }
}
obj.m = 3
obj.m / / 2
Copy the code

When a getter is defined, assignment is meaningless unless a setter is defined. Setters override the default [[Put]] (also known as assignment) operation for individual properties. In general, getters and setters come in pairs (defining only one usually results in unexpected behavior)

var obj = {
    get m() {
        return this._m
    }
    set m(val) {
        this._m = val * 2
    }
}
obj.m = 3
obj.m / / 6
Copy the code

What is reactive

  • When the data property is modified, vue immediately listens and renders to the page
    • Get attributes, how to listen
    • Assign attribute, how to listen
  • The data property is proxied to the VM
    • Why can attributes defined in data be accessed and manipulated by a VM
    var vm = new Vue({
        el: '#app'.data: {
            name: 'wowo'.age: 20
        }
    })
    vm.name // wowo
    vm.age / / 20
    vm.age = 22
    vm.age / / 22
    Copy the code

How does VUe2 achieve responsiveness

Object.defineProperty

var vm = {}
var data = {
    name: 'wowo'
    age: 20,}var key, value
for(key in value) {
    (function watch(key) {
        Object.defineProperty(vm, key, {
            get: function() {
                console.log('get') // Listen to get attributes
                return data[key]
            }
            set: function(val) {
                console.log('set') // Listen for the assignment attribute
                data[key] = val
            }
        })
    })(key)
}
Copy the code

Why did VUe3 switch to proxy

Vue3 switched to proxy to solve vuE2’s defect of using defineProperty

Defects of Object.defineProperty:

  1. Object.defineproperty cannot listen for array changes

    Push () pop() Shift () unshift() splice() sort() reverse()

  2. Object.defineproperty can only hijack the attributes of an Object, so we need to traverse each attribute of each Object. If the attribute value is also an Object, we need to traverse deeply, which is not high performance

Proxy can solve these two defects:

  1. You can listen for changes in the array
  2. Proxy can listen on objects rather than properties. All access to the object must be intercepted through the proxy layer. Therefore, the proxy provides a mechanism for filtering and rewriting external access. A Proxy can simply hijack an entire object and return a new one. Improved performance.

The biggest problem with proxies is that browsers don’t have enough support, and many effects can’t be remedied with PoilyFill.