【问题标题】:Object.defineProperty or .prototype?Object.defineProperty 还是 .prototype?
【发布时间】:2023-03-24 16:56:01
【问题描述】:

我见过两种在 javascript 中实现非原生功能的不同技术, 首先是:

if (!String.prototype.startsWith) {
    Object.defineProperty(String.prototype, 'startsWith', {
        enumerable: false,
        configurable: false,
        writable: false,
        value: function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
        }
    });
}

第二个是:

String.prototype.startsWith = function(searchString, position) {
    position = position || 0;
    return this.lastIndexOf(searchString, position) === position;
}

我知道第二种方法用于将任何方法附加到特定标准内置对象的原型链上,但第一种方法对我来说是新的。 谁能解释它们之间有什么区别,为什么使用一个,为什么不使用一个,它们的意义是什么。

【问题讨论】:

  • enumerableconfigurablewritable 都默认为 false,因此没有必要。无论如何,这样做的好处是,呃,这样定义的属性不是可枚举的、可配置的或可写的,所有这些都是您可能想要的。
  • 是的,但是发现developer.mozilla.org 上的官方文档有点混乱。如果我们可以将属性添加到特定标准内置对象的原型中,那么 defineProperty 实际上做了什么,那是令人困惑的部分。

标签: javascript string object prototype defineproperty


【解决方案1】:

在两种情况下,您要在 String.prototype 中添加一个新属性“startsWith”。

在这种情况下,第一个与第二个不同:

您可以将属性配置为enumerablewritableconfigurable

Writable - true 表示您可以通过分配任何值来更改其值。如果为 false - 您无法更改值

Object.defineProperty(String.prototype, 'startsWith', {
        enumerable: false,
        configurable: false,
        writable: false, // Set to False
        value: function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
        }
    });

var test = new String('Test');

test.startsWith = 'New Value';
console.log(test.startsWith); // It still have the previous value in non strict mode

Enumerable - true 表示将在for in 循环中看到。

Object.defineProperty(String.prototype, 'startsWith', {
        enumerable: true, // Set to True
        configurable: false,
        writable: false, 
        value: function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
        }
    });

var test = new String('Test');

for(var key in test){
   console.log(key)  ;
}

Configurable - true 当且仅当此属性描述符的类型可以更改并且可以从相应对象中删除该属性。

Object.defineProperty(String.prototype, 'startsWith', {
            enumerable: false,
            configurable: false, // Set to False
            writable: false, 
            value: function(searchString, position) {
                position = position || 0;
                return this.lastIndexOf(searchString, position) === position;
            }
        });

    
    delete String.prototype.startsWith; // It will not delete the property
    console.log(String.prototype.startsWith);

还有一个建议,不要更改内置类型的原型

【讨论】:

  • 好吧,也就是说通过使用defineProperty,我们可以将所需属性的行为设置为我们想要的,对吗?
  • 是的,你是对的。如果您将定义一个属性并错过可写、可枚举和可配置的属性,它们的值将默认为false
  • 感谢您的代码演示,这对于理解场景确实是一个帮助..再次感谢..
猜你喜欢
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
  • 2022-12-13
  • 2019-11-29
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多