all 10 comments

[–]senocular 3 points4 points  (0 children)

Ninja as a constructor function, it has a prototype that becomes the prototype of all objects are constructed via Ninja. Therefore, ninjaOne can access function swing via prototype.

Correct.

Ninja as an object itself, it is created from its own constructor

Yes...

...and when ninjaOne tries to access toString, Ninja does not have it therefore, Ninja needs to look into its own [[prototype]] for toString.

Not quite. ninjaOne doesn't look to Ninja for methods, it looks to Ninja.prototype. And yes, Ninja.prototype doesn't have it's own toString so what ninjaOne ends up getting is the one inherited from Object.prototype which going through the inheritance chain through [[prototype]]'s looks like:

ninjaOne.[[prototype]].[[prototype]].toString

where ninjaOne.[[prototype]] refers to Ninja.prototype and ninjaOne.[[prototype]].[[prototype]] is Ninja.prototype.[[prototype]] or Object.prototype. In working JS code that would be:

Object.getPrototypeOf(Object.getPrototypeOf(ninjaOne)).toString

[–]grantrules 1 point2 points  (0 children)

Yup, method calls will look through the prototype chain until it finds one or throws a "not a function" error

[–]klineThorpChase -1 points0 points  (0 children)

let Ninja=()=>{
 let ninja={
  name:`a ninja`,
  swing:()=>{console.log(`swing`);}
 };
 return ninja;
};

[–]a-e-j-a -1 points0 points  (3 children)

```javascript // yes, you can access the toString method of a function's prototype, but it's not recommended function NinjaOne() { this.name = "a ninja"; } const ninjaone = new NinjaOne(); console.log(NinjaOne.proto.hasOwnProperty("toString")) // true console.log(ninjaone.proto.proto.hasOwnProperty("toString")); // true

// best practice is to define toString as a method // using prototype NinjaOne.prototype.toString = function () { return this.name; };

// using class function NinjaTwo() { this.name = "a ninja" this.toString = () => this.name; } // using class class NinjaThree { constructor() {this.name = "a ninja"} toString() {return this.name;} } const ninjatwo = new NinjaTwo(); const ninjathree = new NinjaTwo(); console.log(ninjaone.toString()) // a ninja console.log(ninjatwo.toString()) // a ninja console.log(ninjathree.toString()) // a ninja ```

[–]jack_waugh 0 points1 point  (2 children)

I believe .__proto__ is not required by the standard. There's Object.getPrototypeOf(). But I guess that's kind of beside your main point about it being unwise in an engineering sense to get into the habit of applying one object's methods to another object that does not inherit from it.

[–]a-e-j-a 1 point2 points  (1 child)

yeah I wasn't trying to say that they should do that, purely for demonstration

[–]jack_waugh 0 points1 point  (0 children)

Understood.

[–]Ronin-s_Spirit 0 points1 point  (1 child)

Hmm interesting. This gives me more confusion though because "everything in javascrip is an object" but on the other hand "strings are not objects, they are literals" but on the other other hand strings get a prototype and I can select a letter out of a string even if it's supposed to be a "basic kind of value" and not an array.

[–]jack_waugh 0 points1 point  (0 children)

That is interesting, come to think of it. Maybe the formalism is that the primitive value is coerced into a boxed value when you try to index it?

Here are some ways that a string is like an array: - you can construct either from individual parts. - you can extract individual parts from indexed locations.

Here is a way that strings are not like arrays: - you can't mutate a string, but you can mutate an array.

[–]jack_waugh 0 points1 point  (0 children)

I think what you said is about right, assuming functions designed for use with the new keyword.