Stone said:
I am reading the book "The Concise Guide to Dojo"
From what I have seen here, Dojo is junk as the people maintaining it do not
know what they are doing. Unlearn everything you have read there, and ask
for a refund.
and I saw some code like below on page 11:
decafbad.school.PersonClassic.prototype = {...
I personally did a test like below
==== this code does not work ===
function Person(name) {
this.name = name;
Person.prototype = {
sayHi: function() { alert('hi ' + this.name); }
};
}
var a = new Person("JavaScript");
a.sayHi(); // I got error a.sayHi is not a function
Read the ECMAScript Language Specification, Edition 3 or 5, sections 11.2.2
and 13.2.2:
The internal `[[Prototype]]' property of the newly constructed object
(instance), which is used for prototype chain lookup, is set to the current
value of the `prototype' property of the constructor *before* control enters
the execution context of the constructor (before its `[[Call]]' method is
called).
In the constructor, you are overwriting its `prototype' property, which
previously referred to the same object as the `[[Prototype]]' property of
the instance. But you are not overwriting the `[[Prototype]]' property of
the instance. So the prototype chain lookup for methods of the newly
referred value must fail.
It is also the explanation why you can augment the object referred to by a
constructor's `prototype' property *after* objects have been created with
it, and those objects can use the new properties inherited through the
prototype chain.
however, if I change the code to below style , it worked,
function Person(name) {
this.name = name;
Person.prototype.sayHi = function() { alert('hi ' + this.name);
There's a syntax error, the function expression is incomplete.
}
var a = new Person("JavaScript");
a.sayHi();
My conclusion is, a function's prototype already has some hidden
properties which might be important,
It has, most notably `constructor'.
replace function's prototype is not good idea, only add property to
function's prototype.
That is a fallacy. There are things to consider, though, see below.
It makes no sense *here* to define that method within the constructor,
creating a new function object with identical signature and body on each
constructor call, to begin with. `this' has nothing to do with scope.
So use
function Person(name)
{
this.name = name;
}
Person.prototype.sayHi = function () {
window.alert('hi ' + this.name);
};
var a = new Person("JavaScript");
a.sayHi();
or the equivalent
function Person(name)
{
this.name = name;
}
var a = new Person("JavaScript");
Person.prototype.sayHi = function () {
window.alert('hi ' + this.name);
};
a.sayHi();
or
function Person(name)
{
this.name = name;
}
Person.prototype = {
constructor: Person,
sayHi: function () {
window.alert('hi ' + this.name);
}
};
var a = new Person("JavaScript");
a.sayHi();
if you want to have a "public" method.
(However, with the last approach you have either an *enumerable*
`constructor' property. Or if you do not define it you have one that does
not refer to the instance's constructor; but there is no explicit harm in
having that, the language itself does not use the property.)
Which is why
function Person(name)
{
this.name = name;
}
var a = new Person("JavaScript");
Person.prototype = {
sayHi: function() {
window.alert('hi ' + this.name);
}
};
a.sayHi();
must fail (`Person.prototype' now refers to an object that is not in the
prototype chain of the instance.)
PointedEars