学习一门语言的一种十分无效的办法就是浏览该编程语言开发的优良开源我的项目的源代码。 Vuejs是最好的Javascript开源我的项目之一。
1.变量转字符串
vue/src/shared/util.js
将值转换为字符串是一个十分常见的需要,在Javascript中,有两个函数将值转换为字符串:
String()
JSON.stringify()
这两个性能具备不同的机制,请看上面代码:
console.log(String(null)); // nullconsole.log(JSON.stringify(null)); // null console.log(String(undefined)); // undefined 这里是字符串console.log(JSON.stringify(undefined)); // undefined 这里是变量 console.log(String("abc")); // abcconsole.log(JSON.stringify("abc")); // "abc" console.log(String({ key: "value" })); // [object Object]console.log(JSON.stringify({ key: "value" })); // {"key":"value"} console.log(String([1, 2, 3])); // 1,2,3console.log(JSON.stringify([1, 2, 3])); // [1,2,3] const obj = { title: "devpoint", toString() { return "obj"; },};console.log(String(obj)); // objconsole.log(JSON.stringify(obj)); // {"title":"devpoint"}
从下面输入后果来看,两个办法将对象转为字符串机制存在差别,如何抉择呢?
理论开发中咱们须要将null和undefined转换为字符串时,常常是心愿它返回一个空字符串。
当须要将一个数组和一个一般对象转换为字符串时,常常应用JSON.stringify。
如果须要对象的toString办法被重写,则须要应用String()。
在其余状况下,应用String()将变量转换为字符串。
为了满足以上条件,Vue源码的实现如下:
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);} const obj = { title: "devpoint", toString() { return "obj"; },};console.log(toString(obj)); // objconsole.log(toString([1, 2, 3])); // [1, 2, 3]console.log(toString(undefined)); // ""console.log(toString(null)); // ""
2.一般对象
vue/src/shared/util.js
Object.prototype.toString容许将对象转换为字符串。对于一般对象,当调用此办法时,总是返回[object object]。
const runToString = (obj) => Object.prototype.toString.call(obj);console.log(runToString({})); // [object Object]console.log(runToString({ title: "devpoint" })); // [object Object]console.log(runToString({ title: "devpoint", author: { name: "devpoint" } })); // [object Object]
相似下面这种对象咱们称之为一般对象。
在Javascript中还有一些非凡的对象,如Array、String和RegExp,前端培训它们在Javascript引擎中具备非凡的设计。当它们调用Object.prototype.toString办法时,会返回不同的后果。
const runToString = (obj) => Object.prototype.toString.call(obj);console.log(runToString(["devpoint", 2021])); // [object Array]console.log(runToString(new String("devpoint"))); // [object String]console.log(runToString(/devpoint/)); // [object RegExp]
为了辨别非凡设计对象和一般对象,能够用上面的函数来实现。
function isPlainObject(obj) { return Object.prototype.toString.call(obj) === "[object Object]";}
很多时候,咱们心愿一个函数只执行一次。如果屡次调用该函数,则只会执行第一次。
3.once
vue/src/shared/util.js
很多时候,咱们心愿一个函数只执行一次。如果屡次调用该函数,则只会执行第一次。
function once(fn) { let called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } };} function launchRocket() { console.log("我曾经执行了");}const launchRocketOnce = once(launchRocket);launchRocketOnce();launchRocketOnce();launchRocketOnce();
4.浏览器嗅探
vue/src/core/util/env.js
咱们晓得Javascript能够在浏览器、nodejs等环境中运行,那么如何查看以后的Javascript代码是否在浏览器环境中运行?
如果Javascript在浏览器环境中运行,则会有一个全局对象:window。因而,能够通过以下形式判断环境:
const inBrowser = typeof window !== "undefined";
在Chrome中执行
在Node中执行
如果脚本在浏览器环境中运行,那么咱们能够通过以下形式获取浏览器的userAgent
:
const UA = inBrowser && window.navigator.userAgent.toLowerCase();
在Chrome中执行
不同的浏览器具备不同的userAgent。在Internet Explorer的userAgent中,始终蕴含单词MSIE和Trident。在Chrome浏览器的userAgent中,始终蕴含Chrome一词。
同样,在Android操作系统浏览器中,userAgent始终蕴含单词Android。在iOS中,总是有iPhone、iPad、iPod、iOS一词。
因而,能够通过查看userAgent来确定以后的浏览器供应商和操作系统。
export const UA = inBrowser && window.navigator.userAgent.toLowerCase();export const isIE = UA && /msie|trident/.test(UA);export const isIE9 = UA && UA.indexOf("msie 9.0") > 0;export const isEdge = UA && UA.indexOf("edge/") > 0;export const isAndroid = (UA && UA.indexOf("android") > 0) || weexPlatform === "android";export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || weexPlatform === "ios";export const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;export const isPhantomJS = UA && /phantomjs/.test(UA);export const isFF = UA && UA.match(/firefox\/(\d+)/);
附带阐明一下,Edge和Chrome均基于Chromium,因而两种浏览器的userAgent都蕴含Chrome一词。也就是说,当浏览器的userAgent中蕴含Chrome一词时,该浏览器不肯定是Chrome。const isChrome = UA && /chrome/\d+/.test(UA) && !isEdge。