Jamey's Jamey's
首页
导航站
  • 学习专栏

    • 《HTML》笔记
    • 《CSS》笔记
    • 《JavaScript》笔记
    • 《Vue》笔记
    • 《Git》笔记
    • 《规范》笔记
    • 《软技能》笔记
    • 《面试》笔记
    • 《持续集成&交付&部署》笔记
  • 踩坑专栏

    • 《Element-UI 实践系列》笔记
    • 《移动端 实践系列》笔记
    • 《综合》笔记
  • 配置专栏

    • 《环境系列》笔记
  • 极空间

    • Docker
  • 影视

    • movie
  • 编辑器笔记

    • 开发编辑器
  • 浏览器笔记

    • Chrome
  • Mac笔记

    • Mac
  • 跨界学习

    • 运营
  • 破解合集

    • 破解
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于

Jamey

首页
导航站
  • 学习专栏

    • 《HTML》笔记
    • 《CSS》笔记
    • 《JavaScript》笔记
    • 《Vue》笔记
    • 《Git》笔记
    • 《规范》笔记
    • 《软技能》笔记
    • 《面试》笔记
    • 《持续集成&交付&部署》笔记
  • 踩坑专栏

    • 《Element-UI 实践系列》笔记
    • 《移动端 实践系列》笔记
    • 《综合》笔记
  • 配置专栏

    • 《环境系列》笔记
  • 极空间

    • Docker
  • 影视

    • movie
  • 编辑器笔记

    • 开发编辑器
  • 浏览器笔记

    • Chrome
  • Mac笔记

    • Mac
  • 跨界学习

    • 运营
  • 破解合集

    • 破解
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于
  • 深入系列

  • 专题系列

  • underscore系列

    • underscore 系列之如何写自己的 underscore
    • underscore 系列之链式调用
    • underscore 系列之内部函数 cb 和 optimizeCb
    • underscore 系列之内部函数 restArgs
    • underscore 系列之防冲突与 Utility Functions
      • 一. 防冲突
      • 二. _.identity
      • 三. _.constant
      • 四. _.noop
      • 五. deepGet
      • 六. shallowProperty
      • 七. _.property
      • 八. _.propertyOf
      • 九. _.random
    • underscore 系列之实现一个模板引擎(上)
    • underscore 系列之实现一个模板引擎(下)
    • underscore 系列之字符实体与 _.escape
    • underscore 的源码该如何阅读?
  • ES6系列

  • 模块化

  • 正则表达式

  • 单元测试

  • 微前端

  • 实用函数

  • Rollup

  • 解决方案

  • 《JavaScript》笔记
  • underscore系列
Jamey
2021-11-13
目录

underscore 系列之防冲突与 Utility Functions

# underscore 系列之防冲突与 Utility Functions

# 一. 防冲突

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

var _ = { value: 1 };

// 引入 underscore 后
console.log(_.value); // undefined
1
2
3
4

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

var _ = { value: 1 };

// 引入 underscore 后

// 放弃 "_",使用 "$"
var $ = _.noConflict();

console.log(_.value); // 1

// 使用 underscore 的方法
$.each([1, 2, 3], alert);
1
2
3
4
5
6
7
8
9
10
11

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

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

// 源码一开始的时候便储存之前的 _ 对象
var previousUnderscore = root._;

_.noConflict = function() {
  root._ = previousUnderscore;
  return this;
};
1
2
3
4
5
6
7

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

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

# 二. _.identity

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

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

还记得我们在《underscore 系列之内部函数 cb 和 optimizeCb》 中接触过这个函数吗?

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

_.map = function(arr, iteratee){
  return arr.map(iteratee);
}
1
2
3

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

_.map = function(arr, iteratee){
  if (!iteratee) iteratee = _.identity;
  return arr.map(iteratee);
}
1
2
3
4

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

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

# 三. _.constant

_.constant = function(value) {
  return function() {
    return value;
  };
};
1
2
3
4
5

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

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

value = 2;

getValue(); // 1
getValue(); // 1
1
2
3
4
5
6
7

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

举个例子:

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

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

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

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

# 四. _.noop

_.noop = function(){};
1

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

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

// 不使用 noop
function a(value, callback){
  // 每次使用 callback 都要判断一次
  _.isFunction(callback) && callback();
}

// 使用 noop
function a(value, callback) {
  // 判断一次
  if(!_.isFunction(callback)) callback = _.noop;

  // 以后都可以直接使用
  callback();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 五. 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;
};
1
2
3
4
5
6
7
8

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

var obj = { 
  value: { 
    deepValue: 2
  } 
}

console.log(deepGet(obj, ['value', 'deepValue']));
1
2
3
4
5
6
7

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

# 六. shallowProperty

var shallowProperty = function(key) {
  return function(obj) {
    return obj == null ? void 0 : obj[key];
  };
};
1
2
3
4
5

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

// 获取 arr 所有元素的 name 属性
var arr = [
  {
    value: 1,
    name: 'Kevin'
  },
  {
    value: 2,
    name: 'Daisy'
  }
]

// 普通方式
var names = arr.map(function(item){
  return item.name;
})

// 使用 shallowProperty
var names = arr.map(shallowProperty('name'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 七. _.property

_.property = function(path) {
  if (!_.isArray(path)) {
    return shallowProperty(path);
  }
  return function(obj) {
    return deepGet(obj, path);
  };
};
1
2
3
4
5
6
7
8

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

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

# 八. _.propertyOf

_.propertyOf = function(obj) {
  if (obj == null) {
    return function(){};
  }
  return function(path) {
    return !Array.isArray(path) ? obj[path] : deepGet(obj, path);
  };
};
1
2
3
4
5
6
7
8

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

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

我们写个例子:

// 获取 person 对象的所有属性值
var person = {
  name: 'Kevin',
  age: '18'
};

// 普通方式
var values = Object.keys(person).map((key) => person[key]); // ["Kevin", "18"]

// 使用 _.propertyOf
var values = Object.keys(person).map(_.propertyOf(person)); // ["Kevin", "18"
1
2
3
4
5
6
7
8
9
10
11

# 九. _.random

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

_.random = function(min, max) {
  if (max == null) {
    max = min;
    min = 0;
  }
  return min + Math.floor(Math.random() * (max - min + 1));
};
1
2
3
4
5
6
7

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

#JavaScript underscore
上次更新: 2022/07/01, 17:34:19
underscore 系列之内部函数 restArgs
underscore 系列之实现一个模板引擎(上)

← underscore 系列之内部函数 restArgs underscore 系列之实现一个模板引擎(上)→

Theme by Vdoing | Copyright © 2017-2023 Jamey | blog 闽ICP备19022664号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式