从Vue.js源码中我学到的几个实用函数
大家好,我是若川。欢迎加我微信 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源码中我学到的几个实用函数相关推荐
- 从template到DOM(Vue.js源码角度看内部运行机制)
写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(github.com/answershuto-)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些产出也会对同样想要学习Vue.j ...
- js define函数_不夸张,这真的是前端圈宝藏书!360前端工程师Vue.js源码解析
优秀源代码背后的思想是永恒的.普适的. 这些年来,前端行业一直在飞速发展.行业的进步,导致对从业人员的要求不断攀升.放眼未来,虽然仅仅会用某些框架还可以找到工作,但仅仅满足于会用,一定无法走得更远.随 ...
- vue.js源码学习分享(一)
今天看了vue.js源码 发现非常不错,想一边看一遍写博客和大家分享 /*** Convert a value to a string that is actually rendered. *转换一 ...
- 【Vue.js源码解析 一】-- 响应式原理
前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 课程目标 Vue.js 的静态成员和实例成员初始化过程 首次渲染的过程 数据响应式原理 – 最核心的特性之一 准备工作 ...
- Vue.js 框架源码与进阶 - Vue.js 源码剖析 - 响应式原理
文章目录 一.准备工作 1.1 Vue 源码的获取 1.2 源目录结构 1.3 了解 Flow 1.4 调试设置 1.5 Vue 的不同构建版本 1.6 寻找入口文件 1.7 从入口开始 二.Vue ...
- vue源码解析(3)—— Vue.js 源码构建
Vue.js 源码构建 Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下. 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.json ...
- MVVM架构~knockoutjs系列之从Knockout.Validation.js源码中学习它的用法
说在前 有时,我们在使用一个插件时,在网上即找不到它的相关API,这时,我们会很抓狂的,与其抓狂,还不如踏下心来,分析一下它的源码,事实上,对于JS这种开发语言来说,它开发的插件的使用方法都在它的源码 ...
- Vue.js 源码目录设计
Vue.js 源码目录设计 Vue.js 的源码都在 src 目录下,其目录结构如下. src ├── compiler # 编译相关 ├── core # 核心代码 ├── platforms # ...
- 【Vue.js源码解析 三】-- 模板编译和组件化
前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 模板编译 模板编译的主要目的是将模板 (template) 转换为渲染函数 (render) <div> ...
最新文章
- OpenStack 系列之File Share Service(Manila)详解
- 2019研究生新生大数据出炉!清华园迎来8900多名新主人
- SAP QM物料主数据里QM Material Authorization Group字段
- Android 中 Behavior, NestedScrollingParent, NestedScrollingChild 关系
- 1107 Social Clusters (30 分)【难度: 中 / 知识点: 并查集】
- ifconfig 命令找不到解决
- 字符搜索正则表达式语法详解
- 如何给微软提反馈建议以及bug
- C:01---数据类型与ASCII
- java web 中的乱码
- html弹出保存文件对话框_初步了解CAD的模板文件
- 关于《HTTP权威指南》
- mysql安装框架_MySQL安装详解图文版(V5.5 For Windows)
- 贾俊平统计学思维导图- 第七章参数估计
- CSS 特异度、继承、求值过程简介
- 再见面试官:单例模式有几种写法?
- 德清租房软件测试,张家口商场附近出租房
- 《博德之门3》的许多设计,还不如上世纪的前作
- 手机QQ垃圾文件清理。
- 深度解密Mysql数据库索引
热门文章
- 人才管理是什么意思_上海托管仓库外包仓库管理什么意思
- jenkins war包_Jenkins的安装和部署(jenkins教程)
- 文本框只能输入数字代码
- codeforces 650B - Image Preview
- php执行一条insert插入两条数据其中一条乱码
- 负载测试工具Ripplet
- 全量备份,增量备份,差异备份
- 学习笔记-------两阶段提交 2PC
- java 关闭语句_java.sql.SQLRecoverableException: 关闭的语句
- 数据库:MySQL、SqlServer、Oracle对比