大家好,我是若川。欢迎加我微信 ruochuan12,长期交流学习。今天推荐Vuejs源码中几个实用的方法。

如果想看Vuejs源码,不知道如何下手,一般推荐配置Sourcemap,针对单个问题调试来看,如何调试Vuejs源码,我的vuex源码文章中写了。

点击下方卡片关注我、加个星标,或者查看源码等系列文章。学习源码整体架构系列、年度总结、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-linetypeof 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

最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。


················· 若川出品 ·················

今日话题

有时候付费学习,真的是能节省很多时间,时间也是资源,也是金钱。视频学习和书籍学习都是很好的学习方式,相辅相成,当然,符合自己学习方式才是最重要的。书籍出版一般要经过严格审核流程,网上视频的质量参差不齐。欢迎分享、收藏、点赞、在看我的公众号文章~

一个愿景是帮助5年内前端人走向前列的公众号

可加我个人微信 ruochuan12,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你?(现在还能加我进模拟面试群)

如何拿下阿里巴巴 P6 的前端 Offer

点击方卡片关注我、加个星标,或者查看源码等系列文章。
学习源码整体架构系列、年度总结、JS基础系列

从Vue.js源码中我学到的几个实用函数相关推荐

  1. 从template到DOM(Vue.js源码角度看内部运行机制)

    写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(github.com/answershuto-)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些产出也会对同样想要学习Vue.j ...

  2. js define函数_不夸张,这真的是前端圈宝藏书!360前端工程师Vue.js源码解析

    优秀源代码背后的思想是永恒的.普适的. 这些年来,前端行业一直在飞速发展.行业的进步,导致对从业人员的要求不断攀升.放眼未来,虽然仅仅会用某些框架还可以找到工作,但仅仅满足于会用,一定无法走得更远.随 ...

  3. vue.js源码学习分享(一)

    今天看了vue.js源码  发现非常不错,想一边看一遍写博客和大家分享 /*** Convert a value to a string that is actually rendered. *转换一 ...

  4. 【Vue.js源码解析 一】-- 响应式原理

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 课程目标 Vue.js 的静态成员和实例成员初始化过程 首次渲染的过程 数据响应式原理 – 最核心的特性之一 准备工作 ...

  5. Vue.js 框架源码与进阶 - Vue.js 源码剖析 - 响应式原理

    文章目录 一.准备工作 1.1 Vue 源码的获取 1.2 源目录结构 1.3 了解 Flow 1.4 调试设置 1.5 Vue 的不同构建版本 1.6 寻找入口文件 1.7 从入口开始 二.Vue ...

  6. vue源码解析(3)—— Vue.js 源码构建

    Vue.js 源码构建 Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下. 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.json ...

  7. MVVM架构~knockoutjs系列之从Knockout.Validation.js源码中学习它的用法

    说在前 有时,我们在使用一个插件时,在网上即找不到它的相关API,这时,我们会很抓狂的,与其抓狂,还不如踏下心来,分析一下它的源码,事实上,对于JS这种开发语言来说,它开发的插件的使用方法都在它的源码 ...

  8. Vue.js 源码目录设计

    Vue.js 源码目录设计 Vue.js 的源码都在 src 目录下,其目录结构如下. src ├── compiler # 编译相关 ├── core # 核心代码 ├── platforms # ...

  9. 【Vue.js源码解析 三】-- 模板编译和组件化

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 模板编译 模板编译的主要目的是将模板 (template) 转换为渲染函数 (render) <div> ...

最新文章

  1. OpenStack 系列之File Share Service(Manila)详解
  2. 2019研究生新生大数据出炉!清华园迎来8900多名新主人
  3. SAP QM物料主数据里QM Material Authorization Group字段
  4. Android 中 Behavior, NestedScrollingParent, NestedScrollingChild 关系
  5. 1107 Social Clusters (30 分)【难度: 中 / 知识点: 并查集】
  6. ifconfig 命令找不到解决
  7. 字符搜索正则表达式语法详解
  8. 如何给微软提反馈建议以及bug
  9. C:01---数据类型与ASCII
  10. java web 中的乱码
  11. html弹出保存文件对话框_初步了解CAD的模板文件
  12. 关于《HTTP权威指南》
  13. mysql安装框架_MySQL安装详解图文版(V5.5 For Windows)
  14. 贾俊平统计学思维导图- 第七章参数估计
  15. CSS 特异度、继承、求值过程简介
  16. 再见面试官:单例模式有几种写法?
  17. 德清租房软件测试,张家口商场附近出租房
  18. 《博德之门3》的许多设计,还不如上世纪的前作
  19. 手机QQ垃圾文件清理。
  20. 深度解密Mysql数据库索引

热门文章

  1. 人才管理是什么意思_上海托管仓库外包仓库管理什么意思
  2. jenkins war包_Jenkins的安装和部署(jenkins教程)
  3. 文本框只能输入数字代码
  4. codeforces 650B - Image Preview
  5. php执行一条insert插入两条数据其中一条乱码
  6. 负载测试工具Ripplet
  7. 全量备份,增量备份,差异备份
  8. 学习笔记-------两阶段提交 2PC
  9. java 关闭语句_java.sql.SQLRecoverableException: 关闭的语句
  10. 数据库:MySQL、SqlServer、Oracle对比