Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
299 views
in Technique[技术] by (71.8m points)

node.js - Does Javascript writable descriptor prevent changes on instances?

Answers (please read them below, their respective authors provided valuable insights):

  • "writable: false" prevents assigning a new value, but Object.defineProperty is not an assignement operation and therefore ignores the value of "writable"
  • property attributes are inherited, therefore a property will remain non writable on every subclasses/instances until one subclass (or instance of subclass) changes the value of "writable" back to true for itself

Question:

MDN documentation concerning the property "writable" descriptor states:

writable true if and only if the value associated with the property may be changed with an assignment operator. Defaults to false.

The official ECMA-262 6th edition more or less states the same. The meaning is clear but, to my understanding, it was limited to the original property (i.e. the property on that specific object)

However, please consider the following example (JSFiddle):

//works as expected, overloading complete       
var Parent = function() {};
Object.defineProperty(Parent.prototype, "answer", {
    value: function() { return 42; }
});

var Child = function() {};
Child.prototype = Object.create(Parent.prototype, {
    answer: {
        value: function() { return 0; }
    }
});

var test1 = new Parent();
console.log(test1.answer()); //42
var test2 = new Child();
console.log(test2.answer()); //0

//does not work as expected
var Parent2 = function() {};
Object.defineProperty(Parent2.prototype, "answer", {
    value: function() { return 42; }
});

var Child2 = function() {};
Child2.prototype = Object.create(Parent2.prototype);

test3 = new Parent2();
console.log(test3.answer()); //42
test4 = new Child2();
test4.answer = function() { return 0; };
console.log(test4.answer()); //42

Following this example, we see that, although the property is not writable, it can be overloaded on the prototype of a subclass (test2), as I would expect.

However, when trying to overload the method on an instance of a subclass (test4), it fails silently. I would have expected it to work just as test2. The same happens when trying to overload the property on an instance of Parent.

The same thing occurs in both NodeJS and JSFiddle and, under some conditions, overloading on the instance throws a TypeError concerning the readonly nature of the property.

Could you please confirm to me that this is the expected behaviour ? If so, what is the explanation ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, this is expected behaviour.

it fails silently.

Not exactly. Or: Only in sloppy mode. If you "use strict" mode, you'll get an

Error { message: "Invalid assignment in strict mode", … }

on the line test4.answer = function() { return 0; };

it can be overloaded on the prototype of a subclass (test2), but not an instance of a subclass (test4)

This has nothing to do with instances vs. prototypes. What you didn't notice is that you're using different ways to create the overloading property:

  • an assignment to a property that is inherited and non-writable fails
  • an Object.defineProperty call just creates a new property, unless the object is non-extensible

You can do the same for your instance:

Object.defineProperty(test4, "answer", {
    value: function() { return 42; }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...