JS 可以有与属性同名的 getter 和 setter 方法吗?

问题描述 投票:0回答:2

我想在代码中实现类似 down 的行为:

function Foo(name) {
    this.name = name;
};

var myFoo = new Foo('myName');

myFoo.name('newMyName'); // sets myFoo.name = 'newMyName'
myFoo.name(); // returns 'myName'

但很明显,在那种情况下,我用名称函数覆盖了名称属性。无论如何有可能实现该功能?

javascript setter getter
2个回答
44
投票

在谈论 javascript 中的 getter 和 setter 时,您可能在谈论两个概念之一:

1。 getter 和 setter 作为一个概念,就像在任何其他 OO 语言中一样。

问题中的代码说明了这种情况。在这种情况下,对象的属性很简单,可以是对象或函数的属性。 Javascript 在同一个命名空间中跟踪两者。实际上,函数只是 javascript 中的对象,因此没有像 C 语言中那样为函数单独命名空间的概念。

在这种情况下,“getters”和“setters”只是常规函数,因此需要单独存储值。围绕这个有几种策略。

一种是使用Java中常见的隐式

getSomething()
setSomething()
风格的函数。这允许您从属性名称中消除 getter 和 setter 的歧义,因为 getter 和 setter 在名称中添加了单词“get”和“set”。

第二个策略是你在问题中写的那个。在这种情况下,您需要将属性存储在另一个名称中,以免与 getter/setter 共享相同的名称。

第三种策略是将值存储在闭包中:

    function Foo (name) {
        var name = name;
        this.name = function (str) {
            if (str !== undefined) name = str;
            return name;
        }
    }

请注意,在上面的代码中,值存储在

name
中,但 getter/setter 是
this.name
,这是一个完全不同的变量。这允许您的示例代码按预期工作:

    var me = new Foo('Mark');
    me.name(); // returns Mark
    me.name('Andy'); // sets name to Andy

2。 getter 和 setter 作为 javascript 中的一种机制。

这是遵循 ECMAscript 5 规范的较新版本的 javascript 的功能。此功能允许属性在读取或写入代码时执行代码,类似于 DOM 对象的

.innerHTML
属性在您为其分配内容时调用 HTML 解析器的方式。

getter 和 setter 的语法类似于函数,但引入了

get
set
关键字来代替
function
.

具有 getter 和 setter 的属性的简单示例:

    var me = {
        first_name : "",
        last_name : "",
        get name() {
            return this.first_name + " " + this.last_name;
        },
        set name(str) {
            var n = str.split(/\s+/);
            this.first_name = n.shift();
            this.last_name = n.join(' ');
        }
    }

上面的代码允许您将获取和设置

first_name
last_name
的函数视为变量而不是函数。要使用
name
getter 和 setter,您只需执行以下操作:

    me.name = "James Bond";
    alert(me.first_name); // should alert James
    alert(me.last_name); // should alert Bond
    me.last_name = "Dean";
    alert(me.name); // should alert James Dean

使用javascript的get/set机制,不能在对象中存储同名的值例如:

    var foo = {
        set bar(x) {this.bar=x}
    }

上面的代码将编译但尝试设置 bar:

foo.bar = 1
将由于无限循环导致堆栈溢出 - setter 中的
this.bar=
将再次调用 setter.


0
投票

如果你想使用与属性同名的 JavaScript getter/setter,例如要拦截某些设置器以实现副作用,您可以为您的对象创建一个

Proxy

function editableProxy (myObj) {
    return new Proxy(myObj, {
        toJSON: () => myObj,
        get: function (target, prop) {
            return Reflect.get(myObj, prop);
        },
        set: function (target, prop, receiver) {
            if (prop === 'billTo') {
                myObj.billToId = receiver?.id;
            }
            return Reflect.set(myObj, prop, receiver);
        },
    });
};

所有吸气剂工作正常。设置器正常工作,但如果你设置一个

billTo
它也会设置一个billToId。

let da = {id:123}
let wrapped = editableProxy(da)
let id = wrapped.id // 123
wrapped.id=234
wrapped.id===da.id // true
wrapped.billTo={id:567,name:'Big Bad Bill'} // triggers setter side effect
wrapped.billToId // 567
© www.soinside.com 2019 - 2024. All rights reserved.