从Vue.js源码中我学到了尤大大几点精妙方法

Jacquelyn38
• 阅读 1458

话不多说,赶快试试尤大大教给我们的这几个精妙方法吧!在工作中肯定会用得到。

立即执行函数

页面加载完成后只执行一次的设置函数。

(function (a, b) {  
  console.log(a, b); // 1,2  
})(1, 2);  

通常,全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到。

(function (global) {  
  console.log(global); // Window对象  
})(this);  

多层嵌套三目运算符

三目运算符嵌套的写法,使得代码可读性差,简单业务场景下可以试着使用。

var a = 1;  
var b = 0;  
a == 1 ? (b == 2 ? (b = 3) : (b = 1)) : "";  
console.log(b); // 1  

冻结对象

不可对指定对象增删改。

var emptyObject = Object.freeze({  
  key: "1",  
});  
emptyObject.name = "maomin";  
delete emptyObject.key;  
emptyObject.key = "2";  
console.log(emptyObject);  

密封对象

只能对指定对象进行更改,不可进行增加删除操作。

var sealObject = Object.seal({  
  key: 3,  
});  
sealObject.name = "maomin";  
delete sealObject.key;  
sealObject.key = 4;  
console.log(sealObject); // 4  

检查是否是原始值

function isPrimitive(value) {  
  return (  
    typeof value === "string" ||  
    typeof value === "number" ||  
    // $flow-disable-line  
    typeof value === "symbol" ||  
    typeof value === "boolean"  
  );  
}  

快速检测是否是对象

当我们知道原始值时,它主要用于将对象与原始值区分开来。

function isObject(obj) {  
  return obj !== null && typeof obj === "object";  
}  
console.log(isObject(true)); //false  

检测目标类型

var _toString = Object.prototype.toString;  

function toRawType(value) {  
  return _toString.call(value).slice(8, -1);  
}  
console.log(toRawType([])); // Array  

检查目标是否是有效的数组索引

function isValidArrayIndex(val) {  
  var n = parseFloat(String(val));  
  return n >= 0 && Math.floor(n) === n && isFinite(val);  
}  

检测是否是Promise对象

function isDef(v) {  
  return v !== undefined && v !== null;  
}  
function isPromise(val) {  
  return (  
    isDef(val) &&  
    typeof val.then === "function" &&  
    typeof val.catch === "function"  
  );  
}  
var promiseObj = new Promise(function (resolve, reject) {  
  // 一段耗时的异步操作  
  resolve("成功"); // 数据处理完成  
  // reject('失败') // 数据处理出错  
}).then(  
  (res) => {  
    console.log(res);  
  }, // 成功  
  (err) => {  
    console.log(err);  
  } // 失败  
);  
console.log(isPromise(promiseObj)); // true  

目标转换为字符串

var _toString = Object.prototype.toString;  
function isPlainObject(obj) {  
  return _toString.call(obj) === "[object Object]";  
}  
function toString(val) {  
  return val == null  
    ? ""  
    : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)  
    ? JSON.stringify(val, null, 2)  
    : String(val);  
}  
console.log(toString({ name: 1 })); // {"name": 1}  

转化为数字

将输入值转换为数字以便持久化。如果转换失败,则返回原始字符串。

function toNumber(val) {  
  var n = parseFloat(val);  
  return isNaN(n) ? val : n;  
}  

检测key是否在创建的Map对象内

function makeMap(str, expectsLowerCase) {  
  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];  
      };  
}  
var isBuiltInTag = makeMap("slot,component", true);  
console.log(isBuiltInTag("component")); // true  

删除简单数组中某一项

function remove(arr, item) {  
  if (arr.length) {  
    var index = arr.indexOf(item);  
    if (index > -1) {  
      return arr.splice(index, 1);  
    }  
  }  
}  
console.log(remove([1, 2], 1)); // [1]  

检测对象中是否有指定key

var hasOwnProperty = Object.prototype.hasOwnProperty;  
function hasOwn(obj, key) {  
  return hasOwnProperty.call(obj, key);  
}  
console.log(hasOwn({ name: 1 }, "name")); //true  

将类数组对象转化为真实数组

function toArray(list, start) {  
  start = start || 0;  
  var i = list.length - start;  
  var ret = new Array(i);  
  while (i--) {  
    ret[i] = list[i + start];  
  }  
  return ret;  
}  
console.log(toArray({ 0: 42, 1: 52, 2: 63, length: 3 })); // [42, 52, 63]  

将属性混合到目标对象中

function extend(to, _from) {  
  for (var key in _from) {  
    to[key] = _from[key];  
  }  
  return to;  
}  
console.log(extend({ name: 1 }, { name1: 2 })); // {name:1,name1:2}  

将对象数组合并为单个对象

function extend(to, _from) {  
  for (var key in _from) {  
    to[key] = _from[key];  
  }  
  return to;  
}  
function toObject(arr) {  
  var res = {};  
  for (var i = 0; i < arr.length; i++) {  
    if (arr[i]) {  
      extend(res, arr[i]);  
    }  
  }  
  return res;  
}  
console.log(toObject([{ name: 1 }, { name: 1 }, { name: 2 }, { name1: 3 }])); // {name: 2, name1: 3}  

检测指定项在数组(简单数组、数组对象)中的索引

function isObject(obj) {  
  return obj !== null && typeof obj === "object";  
}  
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 (a instanceof Date && b instanceof Date) {  
        return a.getTime() === b.getTime();  
      } 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 looseIndexOf(arr, val) {  
  for (var i = 0; i < arr.length; i++) {  
    if (looseEqual(arr[i], val)) {  
      return i;  
    }  
  }  
  return -1;  
}  
console.log(looseIndexOf([{ name: 1 }, { name: 2 }], 4)); // -1  
console.log(looseIndexOf([{ name: 1 }, { name: 2 }], { name: 1 })); // 0  

确保函数只调用一次

function once(fn) {  
  var called = false;  
  return function () {  
    if (!called) {  
      called = true;  
      fn.apply(this, arguments);  
    }  
  };  
}  
var callOnce = once(function () {  
  console.log("javascript");  
});  
callOnce(); // javascript  
callOnce();  

定义对象属性

如果你想禁止一个对象添加新属性并且保留已有属性,就可以使用Object.preventExtensions(obj)。

function def(obj, key, val, enumerable) {  
  Object.defineProperty(obj, key, {  
    value: val, // 对象定义属性  
    enumerable: !!enumerable, // 描述属性是否会出现在for in 或者 Object.keys()的遍历中  
    writable: true, // 是否可写  
    configurable: true, // 是否重新定义或者删除  
  });  
}  
var obj = {  
  name: 1,  
};  
def(obj, "name1", 2, true);  
obj.name1 = 3;  
console.log(obj); // {name: 1, name1: 3}  

浏览器环境嗅探

var inBrowser = typeof window !== "undefined";  
var inWeex = typeof WXEnvironment !== "undefined" && !!WXEnvironment.platform;  
var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();  
var UA = inBrowser && window.navigator.userAgent.toLowerCase();  

var isIE = UA && /msie|trident/.test(UA);  
var isIE9 = UA && UA.indexOf("msie 9.0") > 0;  
var isEdge = UA && UA.indexOf("edge/") > 0;  
var isAndroid = (UA && UA.indexOf("android") > 0) || weexPlatform === "android";  
var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || weexPlatform === "ios";  
var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;  
var isPhantomJS = UA && /phantomjs/.test(UA);  
var isFF = UA && UA.match(/firefox\/(\d+)/);  

JS构造函数内的方法与构造函数prototype属性上方法的对比

定义在构造函数内部的方法,会在它的每一个实例上都克隆这个方法;定义在构造函数的 prototype 属性上的方法会让它的所有示例都共享这个方法,但是不会在每个实例的内部重新定义这个方法。如果我们的应用需要创建很多新的对象,并且这些对象还有许多的方法,为了节省内存,我们建议把这些方法都定义在构造函数的 prototype 属性上。当然,在某些情况下,我们需要将某些方法定义在构造函数中,这种情况一般是因为我们需要访问构造函数内部的私有变量。

function A() {  
  this.say = function () {  
    console.log(1);  
  };  
}  
var a = new A();  
a.say();  
function B() {}  
B.prototype.say = function () {  
  console.log(2);  
};  
var b = new B();  
b.say();  
var c = new B();  
c.say();  

获取标签内容(包含标签)

function getOuterHTML(el) {  
  if (el.outerHTML) {  
    return el.outerHTML;  
  } else {  
    var container = document.createElement("div");  
    container.appendChild(el.cloneNode(true));  
    return container.innerHTML;  
  }  
}  

字符串hash值

function hash(str) {  
  var hash = 5381;  
  var i = str.length;  
  while (i) {  
    hash = (hash * 33) ^ str.charCodeAt(--i);  
  }  
  return hash >>> 0;  
}  
console.log(hash("222sd"));// 164533792  

谢谢阅读。

欢迎关注微信公众号 前端历劫之路

回复关键词 电子书,即可获取12本前端热门电子书。

回复关键词 红宝书第4版,即可获取最新《JavaScript高级程序设计》(第四版)电子书。

我创建了一个技术交流、文章分享群,群里有很多大厂的前端大佬,关注公众号后,点击下方菜单了解更多即可加我微信,期待你的加入。

从Vue.js源码中我学到了尤大大几点精妙方法

从Vue.js源码中我学到了尤大大几点精妙方法

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Souleigh ✨ Souleigh ✨
2年前
前端性能优化 - 雅虎军规
无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化35条军规,这样对于优化有一个比较清晰的方向.35条军规1.尽量减少HTTP请求个数——须权衡2.使用CDN(内容分发网络)3.为文件头指定Expires或CacheControl,使内容具有缓存性。4.避免空的
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
2年前
ES6中Generator理解
1\.生成器函数声明  function\ name(args){};2\.yield使用function hello(){    console.log('before hello');  //可看到hello()并不会立刻执行函数, 到第一次next调用时才会    var name 
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这