In our interview process, we often come across the source section, because a good framework usually contains a lot of design concepts and programming practices. I have been looking at the source code for Vue2 and have found a lot of interesting implementations. Now that Vue3 has been released, the fact that Vue2 is an excellent framework does not mean that we have learned some best practices from it.
Those of you who are not interested in Vue can also take a look, because I’m just talking about some JavaScript uses that I learned from the implementation of the framework, and I don’t touch on the concept of Vue.
- Get a string in HTML format with non-tag text (vue/src/compiler/parser/entity-decoder.js)
Suppose we have a string like this:
Var HTML = ‘hello world hello XXX ‘. We now want to extract the non-labeled text and get the following result:
Hello world hello XXX ‘. What should I do? The first thing that comes to mind is regular expressions, but in this case regular expressions can be very annoying to write, so let’s take a look at how the developers of Vue handle it:
- Since this string is
HTML
Text format, we can parse it into the correspondingHTML
Elements. HTML
Elements of thetextContent
Property can be used to getHTML
Element.
The code is as follows:
function decoder(html){
let decoder = document.createElement('div')
decoder.innerHTML = html
console.log(decoder.textContent)
// return decoder.textContent
}
Copy the code
This code creates a div element as the container, sets innerHTML to convert the string to the corresponding HTML element, and then retrieves the textContent through the textContent attribute.
- Determine the operating environment (vue/src/core/util/env.js)
With the rapid development of the front end, we can now run JavaScript code in multiple environments. In order to make adjustments to the different runtime environments, we need to know which environment our code is running in. Let’s take a look at how Vue determines the runtime environment:
const inBrowser = typeof window! = ='undefined'
const inWeex = typeofWXEnvironment ! = ='undefined'&&!!!!! WXEnvironment.platformconst weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
const UA = inBrowser && window.navigator.userAgent.toLowerCase()
const isIE = UA && /msie|trident/.test(UA)
const isIE9 = UA && UA.indexOf('msie 9.0') > 0
const isEdge = UA && UA.indexOf('edge/') > 0
const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
const isChrome = UA && /chrome\/\d+/.test(UA) && ! isEdgeconst isPhantomJS = UA && /phantomjs/.test(UA)
const isFF = UA && UA.match(/firefox\/(\d+)/)
Copy the code
If our code is running in a browser, we’ll definitely get onewindow
Object, so we can go throughconst inBrowser = typeof window ! == 'undefined'
This is the way to judge the environment.
And in the browser, we can go throughwindow
Object to the browseruserAgent
.For different browsersuserAgent
It’s different, likeIE
theuserAgent
It always includesMSIE
And theChrome
theuserAgent
Will containChrome
. Similar to the Android browseruserAgent
Will takeAndroid
. So we go throughuserAgent
You can determine what browser you’re using and what operating system you’re running on. The above code already lists the major browser and operating system judgmentsEdge
The latest version of the browser is also based onChromium
Kernel, so it’suserAgent
Also containChrome
So we have to writeconst isChrome = UA && /chrome\/\d+/.test(UA) && ! isEdge
Such code to determine the current environment isChrome
.
- Determine if a function is user-defined (vue/src/core/util/env.js)
In general, we use only two types of functions, those provided by the environment and those defined by the user, which behave differently when converted to a string:
Array.isArray.toString() // "function isArray() { [native code] }"
function fn(){}
fn.toString() // "function fn(){}"
Copy the code
Function fnName() {[native Code]}; function fnName() {[native Code]}; function fnName() {[native Code]};
function isNative (Ctor){
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
Copy the code
- Implement a function that only executes once (vue/src/shared/util.js)
Many times we want a function to be executed only once, and even if it is called multiple times, it will only be executed the first time, so we can write code like this:
function once (fn) {
let called = false
return function () {
if(! called) { called =true
fn.apply(this.arguments)}}}Copy the code
So we’re going to skip it when we do it later, but this is done using higher-order functions, so you can check out my previous article advanced Tips for JavaScript. Let’s test this method:
You can see that the test method is executed only once.
- Cache function execution results (vue/src/shared/util.js)
As I mentioned in the previous blog, sometimes a function execution is time-consuming and we want to cache the results. This way, when called later, if the parameters are the same, we can skip the calculation and return the result directly. All we need is to implement a cached function that takes the actual function that was called as an argument, and then returns a wrapped function. In this cached function, we can use an object or Map to cache the results.
function cached(fn){
const cache = Object.create(null);
return function cachedFn (str) {
if ( !cache[str] ) {
let result = fn(str);
cache[str] = result;
}
return cache[str]
}
}
Copy the code
- Transform the naming style (vue/src/shared/util.js)
Each of us may use a different programming style, some prefer the camel’s hump, others prefer the small bar connection, to solve this problem, we can write a function to do the uniform conversion. (Such as converting A-B-C to aBC)
const camelizeRE = /-(\w)/g
const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
camelize('a-b-c')
// "aBC"
Copy the code
- Determine the type of the object (vue/src/shared/util.js)
In JavaScript, there are six basic types (Boolean, Number, String, Null, Undefined, Symbol) and an object type, but object types can be subdivided into many types. An object can be an array, a function, and so on. Is there any way we can get the exact type?
We can use the Object. The prototype. ToString converts an Object into a string, if we use {} to create objects, this method always returns [Object Object].
For arrays, regular expressions, and other object types that come with the environment, they return different results.
Using this feature we can determine if an object is the object we created with {} :
function isPlainObject (obj){
return Object.prototype.toString.call(obj) === '[object Object]'
}
Copy the code
And we noticed that the Object. The prototype. The toString (), the return value is always to [the Object tag] form, if we just want this tag, we can take other things out, For simplicity, use either regular or string.prototype.slice ().
function toRawType (value) {
const _toString = Object.prototype.toString
return _toString.call(value).slice(8, -1)
}
toRawType(null) // "Null"
toRawType(/sdfsd/) //"RegExp"
Copy the code
So we can get the type of a variable.
- Convert value to string (vue/src/shared/util.js)
We often need to convert a value to a string. In JavaScript, we have two ways to get a string:
- String()
- JSON.stringify()
However, the implementation mechanism of the two approaches is different:
As we saw, they convert strings based on completely different rules. String(arg) will try to call arg.toString() or arg.valueof (), so which one should we use?
-
For null and undefined, we want to convert it to an empty string
-
We use json.stringify when converting an array or the object we created
-
If the object’s toString method is overridden, then we’ll prefer to use String().
-
In other cases, it’s always String()
To match the above requirements, the Vue developers implemented the following:
function isPlainObject (obj){ return Object.prototype.toString.call(obj) === '[object Object]' } function toString (val) { if(val === null || val === undefined) return ' ' if (Array.isArray(val)) return JSON.stringify(val) if (isPlainObject(val) && val.toString === Object.prototype.toString) return JSON.stringify(val) return String(val) } Copy the code
Is full of harvest day, by reading the best framework code can quickly improve our use of language, strengthen our understanding of the features, summarizes some programming practice, our programming ability also in virtually to get qualitative leap, when very recommend further learning a language with the language to achieve good code to read. Could there be more fun in JavaScript than learning so much just by talking about Vue’s three source files? I hope this article can also give you some help, Happy Coding ~