Js 使用 Object.defineProperty 新增或修改对象方法

Js 使用 Object.defineProperty 新增或修改对象方法

最近工作和学习中,了解到一个十分有用的 Object.defineProperty 方法。其实在我们工作面试的时候,有些面试官就会问到:你知道Vue数据双向绑定的原理嘛?没错,这底层逻辑实现的方式就是先借助 Object.defineProperty 的 get 、set 方法监听修改和读取,通过 数据劫持结合发布者-订阅者模式 的方式来实现数据双向绑定。

语法:

Object.defineProperty(obj, prop, descriptor)

参数:

obj
要定义属性的对象。

prop
要定义或修改的属性的名称或 Symbol 。

descriptor
要定义或修改的属性描述符。

描述:

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

数据描述符:

configurable
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false。

enumerable
当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。

value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined。

writable
当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false。

存取描述符:

get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined。

set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。

案例:

这次用String的endsWith方法为例,若endsWith不存在,使用Object.defineProperty为String新增个endsWith方法。

if (!String.prototype.endsWith) {
    
    
  const endsWith = function (searchStr, strLen) {
    
    
    if (strLen === undefined || strLen > this.length) {
    
    
      strLen = this.length;
    }
    return this.substring(strLen - searchStr.length, strLen) === searchStr;
  };
  if (Object.defineProperty) {
    
    
    Object.defineProperty(String.prototype, 'endsWith', {
    
    
      'value': endsWith,
      'configurable': true,
      'writable': true
    });
  } else {
    
    
    String.prototype.endsWith= endsWith;
  }
}

用Array的at方法为例。

if (!Array.prototype.at) {
    
    
  const atFunc = function (idx) {
    
    
     idx = Math.trunc(idx) || 0; 
     if (idx < 0) idx += this.length;
     if (idx < 0 || idx >= this.length) return undefined;
     return this[idx];
   }
   if (Object.defineProperty) {
    
    
     Object.defineProperty(Array.prototype, "at", {
    
    
       'value': atFunc,
       'configurable': false,
       'writable': false,
	   'configurable': true,
     });
   } else {
    
    
     Array.prototype.at = atFunc;
   }
 }

猜你喜欢

转载自blog.csdn.net/weixin_42927679/article/details/126929677