vue2源码浅读:vue2源码中用的工具类方法

vue2源码中用的工具类方法

// 未定义的
function isUndef(v) {
  return v === undefined || v === null;
}
// 已定义的
function isDef(v) {
  return v !== undefined && v !== null;
}

function isTrue(v) {
  return v === true;
}

function isFalse(v) {
  return v === false;
}

// 检查value是否为基本类型
function isPrimitive(value) {
  return (
    typeof value === "string" ||
    typeof value === "number" ||
    typeof value === "symbol" ||
    typeof value === "boolean"
  );
}

// 判断是否是非null的对象
function isObject(obj) {
  return obj !== null && typeof obj === "object";
}

// 利用 toString() 检测对象类型
// JavaScript 1.8.5 开始,toString() 调用 null 返回[object Null],undefined 返回 [object Undefined]
const _toString = Object.prototype.toString;

function toRawType(value) {
  return _toString.call(value).slice(8, -1);
}

// 是否是纯对象
// 利用 toString(), 检测是否是严格意义的对象类型(非null的对象)
function isPlainObject(obj) {
  return _toString.call(obj) === "[object Object]";
}

// 是否是正则表达式
// 利用 toString(), 检测是否是严格意义的RegExp
function isRegExp(v) {
  return _toString.call(v) === "[object RegExp]";
}

// 检测val是否是一个有效的数组索引
function isValidArrayIndex(val) {
  const n = parseFloat(String(val));
  return n >= 0 && Math.floor(n) === n && isFinite(val);
}

// 检测是否是Promise
function isPromise(val) {
  return (
    isDef(val) &&
    typeof val.then === "function" &&
    typeof val.catch === "function"
  );
}

// 将值转换为正真的字符串
function toString(val) {
  return val == null
    ? ""
    : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
    ? JSON.stringify(val, null, 2)
    : String(val);
}

// 转换为数字
function toNumber(val) {
  const n = parseFloat(val);
  return isNaN(n) ? val : n;
}

// 创建一个映射并返回一个函数,用于检查该映射中是否有一个键。
function makeMap(str, expectsLowerCase) {
  const map = Object.create(null);
  const list = str.split(",");
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true;
  }
  return expectsLowerCase ? (val) => map[val.toLowerCase()] : (val) => map[val];
}

// 检查标签是否为内置标签。
const isBuiltInTag = makeMap("slot,component", true);

// 检查属性是否为保留属性。
const isReservedAttribute = makeMap("key,ref,slot,slot-scope,is");

// 从数组中移除一项
function remove(arr, item) {
  if (arr.length) {
    const index = arr.indexOf(item);
    if (index > -1) {
      return arr.splice(index, 1);
    }
  }
}

// 检查对象是否具有该属性。
const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return hasOwnProperty.call(obj, key);
}

// 创建纯函数的缓存版本
function cached(fn) {
  const cache = Object.create(null);
  return function cachedFn(str) {
    const hit = cache[str];
    return hit || (cache[str] = fn(str));
  };
}

// 将连字符分隔的字符串驼峰化
const camelizeRE = /-(\w)/g;
const camelize = cached((str) => {
  return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ""));
});

// 首字母大写
const capitalize = cached((str) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
});

// 将驼峰字符串转化为中划线连接
const hyphenateRE = /\B([A-Z])/g;
const hyphenate = cached((str) => {
  return str.replace(hyphenateRE, "-$1").toLowerCase();
});

// 将类数组的对象转换为真正的数组
function toArray(list, start) {
  start = start || 0;
  let i = list.length - start;
  const ret = new Array(i);
  while (i--) {
    ret[i] = list[i + start];
  }
  return ret;
}

// 将一个对象合并到目标对象中
// to:目标对象,_from待合并对象
function extend(to, _from) {
  for (const key in _from) {
    to[key] = _from[key];
  }
  return to;
}

// 将数组对象转换为对象
function toObject(arr) {
  const res = {};
  for (let i = 0; i < arr.length; i++) {
    if (arr[i]) {
      extend(res, arr[i]);
    }
  }
  return res;
}

// 判断两个数据是否相等(复杂类型不考虑引用地址)
function looseEqual(a, b) {
  if (a === b) return true;
  const isObjectA = isObject(a);
  const isObjectB = isObject(b);
  if (isObjectA && isObjectB) {
    try {
      const isArrayA = Array.isArray(a);
      const isArrayB = Array.isArray(b);
      if (isArrayA && isArrayB) {
        return (
          a.length === b.length &&
          a.every((e, i) => {
            return looseEqual(e, b[i]);
          })
        );
      } else if (a instanceof Date && b instanceof Date) {
        return a.getTime() === b.getTime();
      } else if (!isArrayA && !isArrayB) {
        const keysA = Object.keys(a);
        const keysB = Object.keys(b);
        return (
          keysA.length === keysB.length &&
          keysA.every((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;
  }
}

// 返回数组中可以找到一个值相等的第一个索引
// (如果value是普通对象,则数组必须包含相同形状的对象),如果不存在,则返回-1。
function looseIndexOf(arr, val) {
  for (let i = 0; i < arr.length; i++) {
    if (looseEqual(arr[i], val)) return i;
  }
  return -1;
}

// 确保一个函数只被调用一次。
function once(fn) {
  let called = false;
  return function () {
    if (!called) {
      called = true;
      fn.apply(this, arguments);
    }
  };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值