话不多说,赶快试试尤大大教给我们的这几个精妙方法吧!在工作中肯定会用得到。
立即执行函数
页面加载完成后只执行一次的设置函数。
1(function (a, b) { 2 console.log(a, b); // 1,2 3})(1, 2); 4
通常,全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到。
1(function (global) { 2 console.log(global); // Window对象 3})(this); 4
多层嵌套三目运算符
三目运算符嵌套的写法,使得代码可读性差,简单业务场景下可以试着使用。
1var a = 1; 2var b = 0; 3a == 1 ? (b == 2 ? (b = 3) : (b = 1)) : ""; 4console.log(b); // 1 5
冻结对象
不可对指定对象增删改。
1var emptyObject = Object.freeze({ 2 key: "1", 3}); 4emptyObject.name = "maomin"; 5delete emptyObject.key; 6emptyObject.key = "2"; 7console.log(emptyObject); 8
密封对象
只能对指定对象进行更改,不可进行增加删除操作。
1var sealObject = Object.seal({ 2 key: 3, 3}); 4sealObject.name = "maomin"; 5delete sealObject.key; 6sealObject.key = 4; 7console.log(sealObject); // 4 8
检查是否是原始值
1function isPrimitive(value) { 2 return ( 3 typeof value === "string" || 4 typeof value === "number" || 5 // $flow-disable-line 6 typeof value === "symbol" || 7 typeof value === "boolean" 8 ); 9} 10
快速检测是否是对象
当我们知道原始值时,它主要用于将对象与原始值区分开来。
1function isObject(obj) { 2 return obj !== null && typeof obj === "object"; 3} 4console.log(isObject(true)); //false 5
检测目标类型
1var _toString = Object.prototype.toString; 2 3function toRawType(value) { 4 return _toString.call(value).slice(8, -1); 5} 6console.log(toRawType([])); // Array 7
检查目标是否是有效的数组索引
1function isValidArrayIndex(val) { 2 var n = parseFloat(String(val)); 3 return n >= 0 && Math.floor(n) === n && isFinite(val); 4} 5
检测是否是Promise对象
1function isDef(v) { 2 return v !== undefined && v !== null; 3} 4function isPromise(val) { 5 return ( 6 isDef(val) && 7 typeof val.then === "function" && 8 typeof val.catch === "function" 9 ); 10} 11var promiseObj = new Promise(function (resolve, reject) { 12 // 一段耗时的异步操作 13 resolve("成功"); // 数据处理完成 14 // reject('失败') // 数据处理出错 15}).then( 16 (res) => { 17 console.log(res); 18 }, // 成功 19 (err) => { 20 console.log(err); 21 } // 失败 22); 23console.log(isPromise(promiseObj)); // true 24
目标转换为字符串
1var _toString = Object.prototype.toString; 2function isPlainObject(obj) { 3 return _toString.call(obj) === "[object Object]"; 4} 5function toString(val) { 6 return val == null 7 ? "" 8 : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) 9 ? JSON.stringify(val, null, 2) 10 : String(val); 11} 12console.log(toString({ name: 1 })); // {"name": 1} 13
转化为数字
将输入值转换为数字以便持久化。如果转换失败,则返回原始字符串。
1function toNumber(val) { 2 var n = parseFloat(val); 3 return isNaN(n) ? val : n; 4} 5
检测key是否在创建的Map对象内
1function makeMap(str, expectsLowerCase) { 2 var map = Object.create(null); 3 var list = str.split(","); 4 for (var i = 0; i < list.length; i++) { 5 map[list[i]] = true; 6 } 7 return expectsLowerCase 8 ? function (val) { 9 return map[val.toLowerCase()]; 10 } 11 : function (val) { 12 return map[val]; 13 }; 14} 15var isBuiltInTag = makeMap("slot,component", true); 16console.log(isBuiltInTag("component")); // true 17
删除简单数组中某一项
1function remove(arr, item) { 2 if (arr.length) { 3 var index = arr.indexOf(item); 4 if (index > -1) { 5 return arr.splice(index, 1); 6 } 7 } 8} 9console.log(remove([1, 2], 1)); // [1] 10
检测对象中是否有指定key
1var hasOwnProperty = Object.prototype.hasOwnProperty; 2function hasOwn(obj, key) { 3 return hasOwnProperty.call(obj, key); 4} 5console.log(hasOwn({ name: 1 }, "name")); //true 6
将类数组对象转化为真实数组
1function toArray(list, start) { 2 start = start || 0; 3 var i = list.length - start; 4 var ret = new Array(i); 5 while (i--) { 6 ret[i] = list[i + start]; 7 } 8 return ret; 9} 10console.log(toArray({ 0: 42, 1: 52, 2: 63, length: 3 })); // [42, 52, 63] 11
将属性混合到目标对象中
1function extend(to, _from) { 2 for (var key in _from) { 3 to[key] = _from[key]; 4 } 5 return to; 6} 7console.log(extend({ name: 1 }, { name1: 2 })); // {name:1,name1:2} 8
将对象数组合并为单个对象
1function extend(to, _from) { 2 for (var key in _from) { 3 to[key] = _from[key]; 4 } 5 return to; 6} 7function toObject(arr) { 8 var res = {}; 9 for (var i = 0; i < arr.length; i++) { 10 if (arr[i]) { 11 extend(res, arr[i]); 12 } 13 } 14 return res; 15} 16console.log(toObject([{ name: 1 }, { name: 1 }, { name: 2 }, { name1: 3 }])); // {name: 2, name1: 3} 17
检测指定项在数组(简单数组、数组对象)中的索引
1function isObject(obj) { 2 return obj !== null && typeof obj === "object"; 3} 4function looseEqual(a, b) { 5 if (a === b) { 6 return true; 7 } 8 var isObjectA = isObject(a); 9 var isObjectB = isObject(b); 10 if (isObjectA && isObjectB) { 11 try { 12 var isArrayA = Array.isArray(a); 13 var isArrayB = Array.isArray(b); 14 if (isArrayA && isArrayB) { 15 return ( 16 a.length === b.length && 17 a.every(function (e, i) { 18 return looseEqual(e, b[i]); 19 }) 20 ); 21 } else if (a instanceof Date && b instanceof Date) { 22 return a.getTime() === b.getTime(); 23 } else if (!isArrayA && !isArrayB) { 24 var keysA = Object.keys(a); 25 var keysB = Object.keys(b); 26 return ( 27 keysA.length === keysB.length && 28 keysA.every(function (key) { 29 return looseEqual(a[key], b[key]); 30 }) 31 ); 32 } else { 33 /* istanbul ignore next */ 34 return false; 35 } 36 } catch (e) { 37 /* istanbul ignore next */ 38 return false; 39 } 40 } else if (!isObjectA && !isObjectB) { 41 return String(a) === String(b); 42 } else { 43 return false; 44 } 45} 46 47function looseIndexOf(arr, val) { 48 for (var i = 0; i < arr.length; i++) { 49 if (looseEqual(arr[i], val)) { 50 return i; 51 } 52 } 53 return -1; 54} 55console.log(looseIndexOf([{ name: 1 }, { name: 2 }], 4)); // -1 56console.log(looseIndexOf([{ name: 1 }, { name: 2 }], { name: 1 })); // 0 57
确保函数只调用一次
1function once(fn) { 2 var called = false; 3 return function () { 4 if (!called) { 5 called = true; 6 fn.apply(this, arguments); 7 } 8 }; 9} 10var callOnce = once(function () { 11 console.log("javascript"); 12}); 13callOnce(); // javascript 14callOnce(); 15
定义对象属性
如果你想禁止一个对象添加新属性并且保留已有属性,就可以使用Object.preventExtensions(obj)。
1function def(obj, key, val, enumerable) { 2 Object.defineProperty(obj, key, { 3 value: val, // 对象定义属性 4 enumerable: !!enumerable, // 描述属性是否会出现在for in 或者 Object.keys()的遍历中 5 writable: true, // 是否可写 6 configurable: true, // 是否重新定义或者删除 7 }); 8} 9var obj = { 10 name: 1, 11}; 12def(obj, "name1", 2, true); 13obj.name1 = 3; 14console.log(obj); // {name: 1, name1: 3} 15
浏览器环境嗅探
1var inBrowser = typeof window !== "undefined"; 2var inWeex = typeof WXEnvironment !== "undefined" && !!WXEnvironment.platform; 3var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); 4var UA = inBrowser && window.navigator.userAgent.toLowerCase(); 5 6var isIE = UA && /msie|trident/.test(UA); 7var isIE9 = UA && UA.indexOf("msie 9.0") > 0; 8var isEdge = UA && UA.indexOf("edge/") > 0; 9var isAndroid = (UA && UA.indexOf("android") > 0) || weexPlatform === "android"; 10var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || weexPlatform === "ios"; 11var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; 12var isPhantomJS = UA && /phantomjs/.test(UA); 13var isFF = UA && UA.match(/firefox\/(\d+)/); 14
JS构造函数内的方法与构造函数prototype属性上方法的对比
定义在构造函数内部的方法,会在它的每一个实例上都克隆这个方法;定义在构造函数的 prototype 属性上的方法会让它的所有示例都共享这个方法,但是不会在每个实例的内部重新定义这个方法。如果我们的应用需要创建很多新的对象,并且这些对象还有许多的方法,为了节省内存,我们建议把这些方法都定义在构造函数的 prototype 属性上。当然,在某些情况下,我们需要将某些方法定义在构造函数中,这种情况一般是因为我们需要访问构造函数内部的私有变量。
1function A() { 2 this.say = function () { 3 console.log(1); 4 }; 5} 6var a = new A(); 7a.say(); 8function B() {} 9B.prototype.say = function () { 10 console.log(2); 11}; 12var b = new B(); 13b.say(); 14var c = new B(); 15c.say(); 16
获取标签内容(包含标签)
1function getOuterHTML(el) { 2 if (el.outerHTML) { 3 return el.outerHTML; 4 } else { 5 var container = document.createElement("div"); 6 container.appendChild(el.cloneNode(true)); 7 return container.innerHTML; 8 } 9} 10
字符串hash值
1function hash(str) { 2 var hash = 5381; 3 var i = str.length; 4 while (i) { 5 hash = (hash * 33) ^ str.charCodeAt(--i); 6 } 7 return hash >>> 0; 8} 9console.log(hash("222sd"));// 164533792 10
谢谢阅读。
欢迎关注微信公众号
前端历劫之路回复关键词
电子书,即可获取12本前端热门电子书。回复关键词
红宝书第4版,即可获取最新《JavaScript高级程序设计》(第四版)电子书。我创建了一个技术交流、文章分享群,群里有很多大厂的前端大佬,关注公众号后,点击下方菜单
了解更多即可加我微信,期待你的加入。


本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/hfGR1XNsTKgWfCZ___Y46g,如有侵权,请联系删除。
