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

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

立即执行函数


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


(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


谢谢阅读。



相关文章
|
13天前
|
缓存 监控 前端开发
JavaScript 实现大文件上传的方法
【10月更文挑战第17天】通过以上步骤和方法,我们可以实现较为可靠和高效的大文件上传功能。当然,具体的实现方式还需要根据实际的应用场景和服务器要求进行调整和优化。
|
2天前
|
JavaScript
JS实现的虚化雪景动态背景特效源码
JS实现的虚化雪景动态背景特效源码是一段基于JS实现的虚化雪景动态背景动画效果代码,非常有意思,欢迎对此特效感兴趣的朋友前来下载参考。
10 4
|
1天前
|
JavaScript
js实现的精美彩色tab选项卡切换特效源码
js实现的精美彩色tab选项卡切换特效源码是一段基于JS实现的文件夹tab选项卡切换效果,拥有彩色、单色两种选择,点击标签选项卡可实现相应的变色效果,非常有意思,欢迎对此段代码感兴趣的朋友前来下载使用。
7 2
|
21小时前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
1天前
|
JavaScript
JS实现简单的打地鼠小游戏源码
这是一款基于JS实现简单的打地鼠小游戏源码。画面中的九宫格中随机出现一个地鼠,玩家移动并点击鼠标控制画面中的锤子打地鼠。打中地鼠会出现卡通爆破效果。同时左上角统计打地鼠获得的分数
9 1
|
2天前
|
JavaScript
js动画循环播放特效源码(上班族的一天)
js动画循环播放特效是一段实现了包含形象的卡通小人吃、睡、电脑工作的网页动画,js循环动画,简单的画面设计。非常丝滑有意思,欢迎对此代码感兴趣的朋友前来下载参考。
11 2
|
2天前
JS+SVG实现的滑块表情评价打分特效源码
JS+SVG实现的滑块表情评价打分特效源码是一段基于JS+SVG制作的表情评价打分效果代码,可以利用鼠标拖动滑块实现表情变化打分效果,支持手机端4个表情分段评价,会随着鼠标滑动的方向而变化
10 2
|
5天前
|
JavaScript 前端开发 Go
异步加载 JS 的方法
【10月更文挑战第24天】异步加载 JavaScript 是提高网页性能和用户体验的重要手段。通过使用不同的方法和技术,可以实现灵活、高效的异步加载 JavaScript。在实际应用中,需要根据具体情况选择合适的方法,并注意处理可能出现的问题,以确保网页能够正常加载和执行。
|
17天前
|
人工智能 JavaScript 网络安全
ToB项目身份认证AD集成(三完):利用ldap.js实现与windows AD对接实现用户搜索、认证、密码修改等功能 - 以及针对中文转义问题的补丁方法
本文详细介绍了如何使用 `ldapjs` 库在 Node.js 中实现与 Windows AD 的交互,包括用户搜索、身份验证、密码修改和重置等功能。通过创建 `LdapService` 类,提供了与 AD 服务器通信的完整解决方案,同时解决了中文字段在 LDAP 操作中被转义的问题。
|
19天前
|
JavaScript 前端开发 UED
vue中vue-router路由懒加载(按需加载)的作用以及常见的实现方法
vue中vue-router路由懒加载(按需加载)的作用以及常见的实现方法
126 1