gpt4 book ai didi

javascript - 我怎样才能使对象数据只能通过JS中的对象方法进行编辑

转载 作者:行者123 更新时间:2023-12-03 02:37:44 25 4
gpt4 key购买 nike

我有一个对象a,其中包含数据以及方法。

var a = {
name:'alisha',
country:'japan',
edit:function(){
// this method should only be edit values of name and country property except this method
}
}


我不知道是否可以做这样的事情,是的,我可以像这样直接编辑它:-

a.name ='alisha2';

但是我不应该以这种方式访问​​。我想调用edit方法,并且edit方法应该为我编辑数据。

a.edit({'name':'alisha update'});

我不知道我们能否做到这一点。可能吗 ?

请不要仅使用纯js的任何库或框架

最佳答案

对您问题的最直接,最简单的答案是“否”。您不能将对象的属性标记为私有...但是,该答案的乐趣所在。让我们看一下实现这种目标的几种不同方法。

注意:为了简化和节省时间,我很可能仅实现所提供的代码示例的一部分。

注意:虽然您的示例显示了一个带对象的edit()方法,但是您可能会改用更显式的访问器/修饰符(出于相同的原因,您想要私有属性),这就是我在下面演示的内容。如果您认为edit()方法更适合您的用例,则可以轻松替换我定义的修饰符。

(可能)最佳答案

约瑟夫·费曼(Joseph Fehrman)概述了最佳答案,直到我写完答案。该解决方案可以通过2种不同的方式来完成。我喜欢下面的显示方式,因为它将约瑟夫提出的IIFE视为可以重用的类/构造函数。



    function A(name, country) {
var _name = name; // I use backslashes as convention to show the variables are meant to be private.
var _country = country;

this.getName = function getName() {
return _name;
};

this.setName = function setName(newName) {
_name = newName;
}
}

var a = new A("Calvin", "USA");
console.log("Name: " + a.getName());





这利用了JS的闭包。只能在 _name定义的范围内访问变量 _countryA。该范围内的其他功能可以访问这些变量,但其他操作则不能。

这种方法的优点是真正的私有数据,只能由 A范围内定义的方法访问。它也不需要任何外部条件,仅利用了每个浏览器都支持的JS功能(希望如此)。这种方法的缺点是您确实没有示例中指定的只读属性。

一个不同的答案

您提到您不想使用任何外部库或框架。但是,如果您愿意使用不需要将其他文件发送到客户端的编译器,则可以使用TypeScript来实现此行为(有点)。同样,您将定义一个可以从中生成 a的类,并且可以将其定义为:

class A {
constructor(private _name: string, private _country: string) { }

/* Option 1 - Similar to the pure JS solution below. */
get name(): string {
return this._name;
}

set name(name: string) {
if(!/^\w+$/.test(name)) {
throw new Error('Invalid name.');
}

this._name = name;
}

/* Option 2 - Closer to what you specified */
get country(): string {
return this._country;
}

setCountry(country: string) {
this._country = country;
}
}

let a = new A('Calvin', 'USA');

// a.name = "New Name"; // Throws an error: "Invalid name."

console.log(a.name);


(您可以运行上面的示例,并在此 TypeScript Playground上对其进行操作)

通过这种方法,您现在拥有一个只读属性( country),可以像在示例代码中演示的那样完全访问该属性,并使用修饰符对其进行显式修改。您还具有外观和行为类似普通属性的属性 name,但是您可以控制读取什么值以及如何通过函数修改该属性。

但是,此方法值得警告:

警告1:显然,使用 name采取的方法可能会产生意想不到的副作用。如果外部代码尝试以设置者禁止的方式修改 name并且未引发错误,则该错误可能永远不会被捕获,并且在执行期间可能会发生错误。话虽如此,我仍然在适当的时候喜欢这种方法。

警告2:TypeScript是JavaScript的超集,并在某些时候被编译(真的被编译为JavaScript)。如果您尝试访问TypeScript之外的任何私有属性,您会发现没有什么阻止您。

TypeScript,但更长

如果我们愿意使用ECMAScript 2015(大多数现代浏览器都支持),则在JS中实现此方法的技巧可能会有些棘手。我们可以这样做,以使窥探者无法查看隐藏的属性并为隐藏的属性定义简单的访问器/修饰符。我们可以使用 Object.defineProperty()来做到这一点。这种方法可能类似于:



    function A(name, country) {
Object.defineProperty(this, '_name', {
configurable: true,
enumerable: false,
writable: true
});

this._name = name;

Object.defineProperty(this, 'name', {
configurable: false,
enumerable: true,
get: function getName() {
return this._name;
}
/**
* If you liked the setter defined in TypeScript, you could accomplish the
* same thing using:
*
* set: function setName(name) {
* this._name = name;
* }
*/
});
}

A.prototype.setName = function setName(name) {
this._name = name;
}

var a = new A('Calvin', 'USA');
console.log(a.name);
a.name = 'Bertrand'; // Silently fails
console.log(a.name); // => "Calvin"





这就是上面的TypeScript示例可以转换为的内容(实际上并不能完全转换为该示例)。有几件事要注意。首先, name是可公开访问的,但不能公开修改。但是, _name(派生 name的值)既可以公开访问又可以修改。我在原型链上定义了 setName()而不是在构造函数中定义 this,部分地证明了这一点。这种方法使 _name很难找到;但是,这也会带来一些负面影响。

由于 _name不是私有的,因此任何人只要知道它的存在就可以故意对其进行修改。即使他们不知道它存在,也可以通过向不知道存在的对象添加属性来覆盖它。例如,如果程序员试图在不克隆原始版本的情况下跟踪对属性的更改,这可能会天真地发生。与几乎所有意外行为一样,这可能会产生意想不到的副作用,这些副作用可能会在以后导致错误。

关于javascript - 我怎样才能使对象数据只能通过JS中的对象方法进行编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48472241/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com