1

I play with following JS code. And I have 2 questions.

1) Why User is not prototype of author_1?

2) Why after the resetting of Author.prototype author_1 becomes not an instanceof Author?

function User(_fname){
    this.fname = _fname;
    return this;
}

function Author(){
    this.book = "Magick of JS";
    return this;
}

Author.prototype = new User('John');
author_1 = new Author;

console.log("=======================");
console.log(author_1 instanceof Author);      // true
console.log(author_1 instanceof User);        // true
console.log(User.isPrototypeOf(author_1));    // false (>>>> 1) WHY? <<<<)
console.log(author_1.constructor);            // User(_fname)
console.log(author_1.__proto__);              // User { fname="John"} 
console.log(Object.getPrototypeOf(author_1)); // User { fname="John"}
console.log(author_1.constructor.prototype);  // User {}

Author.prototype = new User('Alex');
author_2 = new Author;

console.log("=======================");
console.log(author_1 instanceof Author);      // false  (>>>> 2) WHY? <<<<)
console.log(author_1 instanceof User);        // true
console.log(User.isPrototypeOf(author_1));    // false
console.log(author_1.constructor);            // User(_fname)
console.log(author_1.__proto__);              // User { fname="John"} 
console.log(Object.getPrototypeOf(author_1)); // User { fname="John"}
console.log(author_1.constructor.prototype);  // User {}

console.log("=======================");
console.log(author_2 instanceof Author);      // true
console.log(author_2 instanceof User);        // true
console.log(User.isPrototypeOf(author_2));    // false
console.log(author_2.constructor);            // User(_fname)
console.log(author_2.__proto__);              // User { fname="Alex"}
console.log(Object.getPrototypeOf(author_2)); // User { fname="John"}
console.log(author_2.constructor.prototype);  // User {}

console.log("=======================");
console.log(author_1); // User {book: "Magick of JS", fname: "John"}
console.log(author_2); // User {book: "Magick of JS", fname: "Alex"}

Thanks!

UPDATE

Thanks for help! But now I can't understand how author_1 can know that it's an Author

function log(){ console.log.apply(console, arguments) }

function User(_fname){
    this.fname = _fname;
    return this;
}

function Author(){
    this.book = "Magick of JS";
    return this;
}

Author.prototype = new User('John');
author_1 = new Author;

log(author_1);              // User { book="Magick of JS", fname="John"}
log(author_1.__proto__);    // User { fname="John"}
log(author_1.constructor);  // User(_fname)

log(author_1 instanceof Author); // true

// How author_1 kowns that it's an Author? Where is property?
// Can I find it in web inspector? Or it's hidden value?
4
  • 2
    Don't you need () after new Author for both author_1 and author_2? That may vastly change your results. Commented Oct 23, 2013 at 13:57
  • 2
    @ScottMermelstein no, you don't. It's optional. new ConstructorFunction behaves exactly the same as new ConstructorFunction(). It's just less common syntax. Commented Oct 23, 2013 at 13:58
  • OP, why are you doing return this inside the functions acting like constructors? Commented Oct 23, 2013 at 14:02
  • By default any constructor function makes return this, I just do it visibly. Commented Oct 23, 2013 at 18:49

2 Answers 2

4
  1. The object "User" is the constructor function. Each instance of "User" is a different object. Hence, User.isPrototypeOf(author_1) is false because the object "User" is simply not the prototype; that instance you created is the prototype.

  2. When you change the prototype, the object previously created retains its original prototype chain, and hence it appears to the runtime system not to be an instance of "Author" anymore.

Sign up to request clarification or add additional context in comments.

3 Comments

I've started to write the answer, but I can add to this one as well: 1) you can also take a look developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… for the usage of isPrototypeOf
+1. Inheritance in JavaScript is between objects and not classes. There is no real (atm) notion of classes in the language and typing is behavioral (and stronger in a sense). User is just a function that is used as a template for your objects, it's not a class.
Thanks. There are also several extremely clear and thorough answers on Stackoverflow by T.J. Crowder that give a great guide to this stuff, and really solid coding approaches too.
3

1) The new operator acts like this:

var x = new F()
// approximately the same as this:
x = Object.create(F.prototype); // x inherits from the prototype of F
F.call(x); // F is called with x as 'this'

For this reason:

User.isPrototypeOf(author_1) // false because 
User.prototype.isPrototypeOf(author_1) // true

Resources: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

2) Instanceof acts like this:

x instanceof F
// aproximately the same as this:
Object.getPrototypeOf(x) === F.prototype

When you do F.prototype = {}, you changed the property of F, but you didn't change the prototype chain of the already created object x.

var initialProto = {id:1};
F.prototype = initialProto;
var x = new F();

var anotherProto = {id:2};
F.prototype = anotherProto ;

Object.getPrototypeOf(x) === initialProto // true;
initialProto === anotherProto // obviously false

Resources: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.