Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Some of the fun functions I found during a recent study of Vue source code


May 31, 2021 Article blog



Recently in-depth study of vue source code, the learning process, see some fun functional methods to collect and share, I hope to help you to learn js in depth. If everyone can understand these functions at a glance, the technology is still good Oh.

1. Data type judgment

Object.prototype.toString.call() returns a data format of the type object, and then uses slice to intercept the 8th to the last bit, resulting in Object

var _toString = Object.prototype.toString;
function toRawType (value) {
  return _toString.call(value).slice(8, -1)
}

Run the results test

toRawType({}) //  Object 
toRawType([])  // Array    
toRawType(true) // Boolean
toRawType(undefined) // Undefined
toRawType(null) // Null
toRawType(function(){}) // Function

2. Use closures to construct map cache data

Vue to determine whether the component name we write is html built-in labels, if you use array class traversal then will have to loop many times to get the results, if the array into an object, the label name is set to the key of the object, then do not have to traverse the lookup in turn, only need to find once to get results, improve the efficiency of the search.

function makeMap (str, expectsLowerCase) {
    // 构建闭包集合map
    var map = Object.create(null);
    var list = str.split(',');
    for (var i = 0; i < list.length; i++) {
      map[list[i]] = true;
    }
    return expectsLowerCase
      ? function (val) { return map[val.toLowerCase()]; }
      : function (val) { return map[val]; }
}

With closures, you can simply call isHTMLTag each time you decide if it's a built-in label

var isHTMLTag = makeMap('html,body,base,head,link,meta,style,title')
console.log('res', isHTMLTag('body')) // true

3. Flattening of a two-dimensional array

_createElement vue_createElement the simpleNormalizeChildren function is used to format incoming children in order to flatten the array and flatten the two-dimensional array, similar to the flatten method in lodash

// 先看lodash中的flatten
_.flatten([1, [2, [3, [4]], 5]])
// 得到结果为  [1, 2, [3, [4]], 5]


// vue中
function simpleNormalizeChildren (children) {
  for (var i = 0; i < children.length; i++) {
    if (Array.isArray(children[i])) {
      return Array.prototype.concat.apply([], children)
    }
  }
  return children
}


// es6中 等价于
function simpleNormalizeChildren (children) {
   return [].concat(...children)
}

4. Method interception

Vue uses Object.defineProperty to collect dependencies, triggering an updated view, but the array cannot monitor changes in the data, but why can an array trigger page updates when using methods such as push pop because vue intercepts these methods internally.

// 重写push等方法,然后再把原型指回原方法


 var ARRAY_METHOD = [ 'push', 'pop', 'shift', 'unshift', 'reverse',  'sort', 'splice' ];
 var array_methods = Object.create(Array.prototype);
 ARRAY_METHOD.forEach(method => {
   array_methods[method] = function () {
     // 拦截方法
     console.log('调用的是拦截的 ' + method + ' 方法,进行依赖收集');
     return Array.prototype[method].apply(this, arguments);
   }
 });

Run the results test

var arr = [1,2,3]
arr.__proto__ = array_methods // 改变arr的原型
arr.unshift(6) // 打印结果: 调用的是拦截的 unshift 方法,进行依赖收集

5. The implementation of inheritance

Vue.extend is called Vue.extend instantiation component in Vue.extend is VueComponent constructor, and VueComponent inherits Vue with Object.create so Vue and Vue.extend not very different in normal development. This side mainly learns to implement inheritance using es5 native methods, of course, the class class in es6 is inherited directly with extends.

  // 继承方法 
  function inheritPrototype(Son, Father) {
    var prototype = Object.create(Father.prototype)
    prototype.constructor = Son
    // 把Father.prototype赋值给 Son.prototype
    Son.prototype = prototype
  }
  function Father(name) {
    this.name = name
    this.arr = [1,2,3]
  }
  Father.prototype.getName = function() {
    console.log(this.name)
  }
  function Son(name, age) {
    Father.call(this, name)
    this.age = age
  }
  inheritPrototype(Son, Father)
  Son.prototype.getAge = function() {
    console.log(this.age)
  }

Run the results test

var son1 = new Son("AAA", 23)
son1.getName()            //AAA
son1.getAge()             //23
son1.arr.push(4)          
console.log(son1.arr)     //1,2,3,4


var son2 = new Son("BBB", 24)
son2.getName()            //BBB
son2.getAge()             //24
console.log(son2.arr)     //1,2,3

6. Perform once

The once method is relatively simple, and it would be nice to implement it directly with a closure

function once (fn) {
  var called = false;
  return function () {
    if (!called) {
      called = true;
      fn.apply(this, arguments);
    }
  }
}

7. Shallow copy

Simple deep copy we can use JSON.stringify() but the looseEqual shallow copy in vue source code is also very interesting, first type judgment and then recursive call, overall is not difficult, learn the idea.

function looseEqual (a, b) {
  if (a === b) { return true }
  var isObjectA = isObject(a);
  var isObjectB = isObject(b);
  if (isObjectA && isObjectB) {
    try {
      var isArrayA = Array.isArray(a);
      var isArrayB = Array.isArray(b);
      if (isArrayA && isArrayB) {
        return a.length === b.length && a.every(function (e, i) {
          return looseEqual(e, b[i])
        })
      } else if (!isArrayA && !isArrayB) {
        var keysA = Object.keys(a);
        var keysB = Object.keys(b);
        return keysA.length === keysB.length && keysA.every(function (key) {
          return looseEqual(a[key], b[key])
        })
      } else {
        /* istanbul ignore next */
        return false
      }
    } catch (e) {
      /* istanbul ignore next */
      return false
    }
  } else if (!isObjectA && !isObjectB) {
    return String(a) === String(b)
  } else {
    return false
  }
}
function isObject (obj) {
  return obj !== null && typeof obj === 'object'
}

Here's a look at some of the fun functions I found during a recent study of Vue source code by W3Cschool编程狮