博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
underscore 系列之防冲突与 Utility Functions
阅读量:6577 次
发布时间:2019-06-24

本文共 4305 字,大约阅读时间需要 14 分钟。

防冲突

underscore 使用 _ 作为函数的挂载对象,如果页面中已经存在了 _ 对象,underscore 就会覆盖该对象,举个例子:

var _ = {value: 1 }// 引入 underscore 后console.log(_.value); // undefined

所以 underscore 提供了 noConflict 功能,可以放弃 underscore 的控制变量 _,返回 underscore 对象的引用。

var _ = {value: 1 }// 引入 underscore 后// 放弃 "_",使用 "$"var $ = _.noConflict();console.log(_.value); // 1// 使用 underscore 的方法$.each([1, 2, 3], alert);

那么 noConflict 函数是如何实现的呢?

首先,在 underscore 执行的时候,会储存之前的 _ 对象,然后当执行 noConflict 函数的时候,再将之前储存的 _ 对象赋给全局对象,最后返回 underscore 对象。这样,我们就可以利用返回的 underscore 对象使用 underscore 提供的各种方法。

// 源码一开始的时候便储存之前的 _ 对象var previousUnderscore = root._;_.noConflict = function() {    root._ = previousUnderscore;    return this;};

是的,就是这么简单。你可以轻松为你的函数库添加防冲突功能。

接下来我们看 underscore 中的一些功能函数。

_.identity

_.identity = function(value) {    return value;};

看起来匪夷所思的一个函数,传入一个值,然后返回该值,为什么不直接使用该值呢?

还记得我们在中接触过这个函数吗?

如果我们自己编写了一个 _.map 函数:

_.map = function(arr, iteratee){    return arr.map(iteratee)}

然而当我们这样使用 _.map([1, 2, 3]) 时便会报错,因为我们没有传入 iteratee 函数,然而使用 underscore 却没有问题,结果是返回一个相同的新数组,原因就在于当 iteratee 为 undefined 的时候,underscore 视为传入了 _.identity 函数。就相当于:

_.map = function(arr, iteratee){    if (!iteratee) iteratee = _.identity    return arr.map(iteratee)}

简而言之,如果我们想要复制一个数组:

var clonedArr = [1, 2, 3].map(_.identity) // [1, 2, 3]

_.constant

_.constant = function(value) {    return function() {        return value;    };};

该函数传入一个 value,然后返回一个返回该 value 的函数,这又有什么用呢?我们来看个 demo:

var value = 1;var getValue = _.constant(value);value = 2;getValue(); // 1getValue(); // 1

这很容易让人想到 ES6 的 const,我一开始以为就是用来表示 ES6 的 const ,后来看了这个函数起源的 issue,才发现并非如此,它其实像下面的 _.noop 函数一样可以作为默认函数使用。

举个例子:

_.select(collection, filterFunction || function() { return true; })

我们根据 filterFunction 筛选 collection 中符合条件的元素,如果没有传 filterFunction,我们就返回所有的元素,如果有 _.constant 函数,我们可以将其简化为:

_.select(collection, filterFunction || _.constant(true))

尽管没有什么大的改变,但是语义更加明确。

_.noop

_.noop = function(){};

一个空函数,看起来依旧没什么用……

noop 函数可以用于作为默认值,这样就可以省去是否存在的判断,举个例子:

// 不使用 noopfunction a(value, callback){    // 每次使用 callback 都要判断一次    _.isFunction(callback) && callback()}// 使用 noopfunction a(value, callback) {    // 判断一次    if(!_.isFunction(callback)) callback = _.noop;    // 以后都可以直接使用    callback()}

deepGet

var deepGet = function(obj, path) {    var length = path.length;    for (var i = 0; i < length; i++) {        if (obj == null) return void 0;        obj = obj[path[i]];    }    return length ? obj : void 0;};

deepGet 用于获得对象深层次的值。举个例子:

var obj = {     value: {         deepValue: 2    } }console.log(deepGet(obj, ['value', 'deepValue']))

使用这个函数,可以避免深层次取值时,因为没有其中的一个属性,导致的报错。

shallowProperty

var shallowProperty = function(key) {    return function(obj) {      return obj == null ? void 0 : obj[key];    };};

shallowProperty 也是用于获取对象的属性,也许你会好奇在开发中,直接使用. 不就可以获取对象的属性了,为什么还要写成这样呢?我们来举个例子:

// 获取 arr 所有元素的 name 属性var arr = [    {        value: 1,        name: 'Kevin'    },    {        value: 2,        name: 'Daisy'    }]// 普通方式var names = arr.map(function(item){    return item.name;})// 使用 shallowPropertyvar names = arr.map(shallowProperty('name'))

_.property

_.property = function(path) {    if (!_.isArray(path)) {      return shallowProperty(path);    }    return function(obj) {      return deepGet(obj, path);    };};

_.property 结合了 deepGet 和 shallowProperty,可以获取元素深层次的值。上面一个例子也可以写成:

var names = arr.map(_.property('name'))

_.propertyOf

_.propertyOf = function(obj) {    if (obj == null) {        return function(){};    }    return function(path) {        return !Array.isArray(path) ? obj[path] : deepGet(obj, path);    };};

_.property 返回一个函数,这个函数返回任何传入的对象的指定属性。

_.propertyOf_.property 相反。需要一个对象,并返回一个函数,这个函数将返回一个提供的属性的值。

我们写个例子:

// 获取 person 对象的所有属性值var person = {    name: 'Kevin',    age: '18'};// 普通方式var values = Object.keys(person).map((key) => person[key]); // ["Kevin", "18"]// 使用 _.propertyOfvar values = Object.keys(person).map(_.propertyOf(person)); // ["Kevin", "18"

_.random

返回一个 min 和 max 之间的随机整数。如果你只传递一个参数,那么将返回 0 和这个参数之间的整数。

_.random = function(min, max) {    if (max == null) {      max = min;      min = 0;    }    return min + Math.floor(Math.random() * (max - min + 1));  };

注意:该随机值有可能是 min 或 max。

underscore 系列

underscore 系列目录地址:。

underscore 系列预计写八篇左右,重点介绍 underscore 中的代码架构、链式调用、内部函数、模板引擎等内容,旨在帮助大家阅读源码,以及写出自己的 undercore。

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

转载地址:http://ikmjo.baihongyu.com/

你可能感兴趣的文章
电脑上怎样压缩图片大小
查看>>
新来的发一个帖子
查看>>
Nginx 支持webSocket 响应403
查看>>
lnmp安装
查看>>
3.两种密钥配对方法,很简单哦《Mr.Robot》
查看>>
FTP工作方式
查看>>
Linux之安装部署squid代理服务器
查看>>
Linux文件和目录管理常用命令(中)
查看>>
Configure HUE to store data in MySQL
查看>>
我的友情链接
查看>>
Server2008 中AD的部署
查看>>
Enhanced VMotion Compatibility (EVC) 功能介绍和实战设置
查看>>
RabbitMQ 流控制学习
查看>>
Ubuntu16.04 ssh安及root登录
查看>>
一个工程两个target
查看>>
linux 给文件夹权限
查看>>
用复制mysql/data 文件夹 下面的数据库的形式来复制数据库出现的问题
查看>>
C语言dos程序源代码分享(进制转换器)
查看>>
php项目中常用的log日志记录方法
查看>>
Android--实现点击一次返回键返回桌面而不是退出应用
查看>>