1

lodash的isXXX方法们

_.isObject

是否为对象 (e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

实际上判断!!value排除掉了nullNaN两种特殊值,

有可能会疑问,type == 'function',函数是对象的一种。

new string('')在这里是被当作对象处理的。

以字符串为例,new String('')这种我们称之为字符串对象,而我们常用的var str = ''或者var str = String(''),我们称之为基本字符串。当我们执行时,js会自动将基础字符串转换为字符串对象,再调用字符串原型上的方法。

_.isObjectLike

检查 value 是否是 类对象。 如果一个值是类对象,那么它不应该是 null,而且 typeof 后的结果是 "object"。
function isObjectLike(value){
    return !!value && typeof value == 'object';
}

_.isPlainObject

查 value 是否是普通对象。 也就是说该对象由 Object 构造函数创建,或者 [[Prototype]] 为 null 。

Native objects: Object (constructor), Date, Math, parseInt, eval, string methods like indexOf and replace, array methods, ...

Host objects (assuming browser environment): window, document, location, history, XMLHttpRequest, setTimeout, getElementsByTagName, querySelectorAll, ...
var objectTag = '[object Object]';
var getPrototype = overArg(Object.getPrototypeOf, Object);

function isPlainObject(value) {
  if (!isObjectLike(value) || // 不是对象
      objectToString.call(value) != objectTag || isHostObject(value)) {
      /**
      * - hostobject,像setTimeout,window.location.,window,document这种就是hostObject。
      * 
      */
    return false;
  }
  var proto = getPrototype(value); //- 获取prototype.正如方法描述所说,如果没有proto,直接就返回true了。
  if (proto === null) {
    return true;
  }
  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
  return (typeof Ctor == 'function' &&
    Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
}

constructor返回创建实例对象的 Object 构造函数的引用.

如下例子

var Foo = function Foo(){}
var foo = new Foo();

foo.constructor === Foo;
// => true

// case 0 假如我们此时传的是foo,则Ctor实际上指的是
var Ctor = Foo.prototype.constructor

Foo.prototype.constructor.toString()
// => "function (){}"

Object.prototype.constructor.toString()
// => "function Object() { [native code] }"  当前结果为Object.toString()

_.isLength(value)

检查 value 是否为有效的类数组长度。
//js中最大的整数
var MAX_SAFE_INTEGER = 9007199254740991;
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

有效的数组长度有2个前提

  • number类型
  • 有效的正整数

_.isFunction

检查 value 是否是 Function 对象。

实际上,我们可以使用typeof fn === 'function'来判断是否是数组,但是在某些环境(比如Safari8-9 会返回‘object’)。通过object.toString规避了这个问题,提高了代码的健壮性。

GeneratorgenTag可以看这个issue https://github.com/lodash/lod...,这个问题,规避的是在nodejs中的问题。

function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

_.isArray

判断是否数组

借用的是var isArray = Array.isArray

_.isArrayBuffer

检查 value 是否是 ArrayBuffer 对象。
var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;

var arrayBufferTag = '[object ArrayBuffer]';

function baseIsArrayBuffer(value) {
  return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
}

部分代码是跟node相关,暂不处理。从baseIsArrayBuffer看,仍是通过Object.toString返回的字符串做的判读。ArrayBuffer是es6中新增。

_.isArrayLike

是否类数组

该方法对类数组有个定义,value不是一个方法,并且value.length是一个有效的值。(大于等于0,小于等于Number.MAX_SAFE_INTEGER

你可能要注意一下,字符串"abc"这种也被毁当作一个arraylike

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

_.isArrayLikeObject

功能同isArrayLike相同,只是它前提判断是否是一个对象。也就是'abc'这种字符串返回false
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

_.isArguments

判断是否是类arguments对象

function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}
  • arguments是类数组
  • arguments有callee属性,指向当前执行的函数。
  • arguments有length属性
  • arguments[@@iterator]返回一个新的Array迭代器对象,该对象包含参数中每个索引的值。
  • callee属性不可枚举

_.isBoolean

判断是否为Boolean类型
function isBoolean(value) {
  return value === true || value === false ||
    (isObjectLike(value) && objectToString.call(value) == boolTag);
}

对象这个判断可能会有点迷惑,实际上是证明了这种情况

var bol = new Boolean('true')
typeof bol 
// object

_.isDate

是否为Date类型
var dateTag = '[object Date]';

function baseIsDate(value) {
  return isObjectLike(value) && objectToString.call(value) == dateTag;
}

判断条件为value是对象类型,在判断toString返回的值是否为[object Date]

_.isElement

是否为dom element
function isElement(value) {
  return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
}
nodeType是什么?http://www.w3school.com.cn/js...

如果节点是元素节点,返回1。
如果节点是属性节点,返回2.

所以判断是dom element是,是对象,是元素节点。

_.isEmpty

    /**
     * Checks if `value` is an empty object, collection, map, or set.
     * 检查`value`是否是一个空的对象,collection,map或者set
     * Objects are considered empty if they have no own enumerable string keyed
     * properties.
     * 如果对象没有以enumerable的字符串属性,被认为是空的。
     * Array-like values such as `arguments` objects, arrays, buffers, strings, or
     * jQuery-like collections are considered empty if they have a `length` of `0`.
     * 像arugments对象,数组,buffers,strings,或者jquery对象被认为是空的如果它们的length属性为0
     * Similarly, maps and sets are considered empty if they have a `size` of `0`.
     *同样,maps和sets对象的length属性为空,我们也认为它是empty
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is empty, else `false`.
     * @example
     *
     * _.isEmpty(null);
     * // => true
     *
     * _.isEmpty(true);
     * // => true
     *
     * _.isEmpty(1);
     * // => true
     *
     * _.isEmpty([1, 2, 3]);
     * // => false
     *
     * _.isEmpty({ 'a': 1 });
     * // => false
     */
    function isEmpty(value) {
      if (isArrayLike(value) &&
          (isArray(value) || typeof value == 'string' ||
            typeof value.splice == 'function' || isBuffer(value) || isArguments(value))) {
        return !value.length;
      }
      var tag = getTag(value);
      if (tag == mapTag || tag == setTag) { // map或者set类型,判断size存在,不存在是empty
        return !value.size;
      }
      if (isPrototype(value)) { // 传入的是一个prototype对象,而且没有任何属性
        return !nativeKeys(value).length;
      }
      for (var key in value) {
      // 用for in 来判断value,如果value上key不是在原型链上,就有问题。
        if (hasOwnProperty.call(value, key)) {
          return false;
        }
      }
      return true;
    }
// isPrototype
/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

判断圆形对象。

String.prototype.constructor.prototype === String.prototype

最普通的一个
301 声望41 粉丝

永远不要做你擅长的事。


引用和评论

0 条评论