why prototype is undefined - javascript

I known this has been asked hundreds of times, however, I can't seem to grasp the concept of prototype
Here's my sample script
var config = {
writable: true,
enumerable: true,
configurable: true
};
var defineProperty = function(obj, name, value) {
config.value = value;
Object.defineProperty(obj, name, config);
}
var man= Object.create(null);
defineProperty(man, 'sex', "male");
var person = Object.create(man);
person.greet = function (person) {
return this.name + ': Why, hello there, ' + person + '.'
}
var p=Object.getPrototypeOf(person);
alert(p.sex);//shows male
person.prototype.age=13;//why there is a error said the prototype is undefined? I thought it supposed be man object...
var child=function(){}
child.prototype.color="red";//why this line doesn't show error? both child and person are an object .
alert(child.prototype.color);//shows red
var ch=Object.getPrototypeOf(child);
alert(ch.color);//why it is undefined? it is supposed red.
Hope you can give me some helps... thanks.
Updated:
Thanks your guys kindly help, Based on Elclanrs's answer, Below is what I learned.
Function is the one of the build-in objects in javascript. the 3 format creation function object are equal.
var function_name = new Function(arg1, arg2, ..., argN, function_body)
function function_name(arg1, arg2, ..., argN)
{
...
}
var function_name=function(arg1, arg2, ..., argN)
{
...
}
So, that is why create a prototype chain we have to create a function and then call it with the new keyword .
Function.prototype is the reference to All the Function object prototype.
Cheers

The prototype property only exists on functions, and person is not a function. It's an object.
Here's what's happening:
var man = Object.create(null); // man (object) -> null
man.sex = "male";
var person = Object.create(man); // person (object) -> man (object) -> null
person.greet = function () { ... };
var p = Object.getPrototypeOf(person); // man (object) -> null
alert(p.sex); // p is the same object as man
person.prototype.age = 13; // person doesn't have a prototype
var child = function () {}; // child (function) -> Function.prototype
// -> Object.prototype -> null
child.prototype.color = "red"; // child has a prototype
var ch = Object.getPrototypeOf(child); // Function.prototype
alert(ch.color); // ch is not the same as color.prototype
// ch is Function.prototype
For more information I suggest you read this answer: https://stackoverflow.com/a/8096017/783743
Edit: To explain what's happening in as few words as possible:
Everything in JavaScript is an object except primitive values (booleans, numbers and strings), and null and undefined.
All objects have a property called [[proto]] which is not accessible to the programmer. However most engines make this property accessible as __proto__.
When you create an object like var o = { a: false, b: "something", ... } then o.__proto__ is Object.prototype.
When you create an object like var o = Object.create(something) then o.__proto__ is something.
When you create an object like var o = new f(a, b, ...) then o.__proto__ is f.prototype.
When JavaScript can't find a property on o it searches for the property on o.__proto__ and then o.__proto__.__proto__ etc until it either finds the property or the proto chain ends in null (in which case the property is undefined).
Finally, Object.getPrototypeOf(o) returns o.__proto__ and not o.prototype - __proto__ exists on all objects including functions but prototype only exists on functions.

I think you might be mixing concepts. Try grasping the concept of prototypes with classic prototype inheritance first, then you can get into all the new Object stuff.
In JavaScript, every object (numbers, strings, objects, functions, arrays, regex, dates...) has a prototype which you can think of as a collection of methods (functions) that are common to all current and future instances of that object.
To create a prototype chain you have to create a function and then call it with the new keyword to specify that it is a constructor. You can think of constructors as the main function that takes the parameters necessary to build new instances of your object.
Having this in mind, you can extend native objects or create your own new prototype chains. This is similar to the concept of classes but much more powerful in practice.
Similar to your example, you could write a prototype chain like this:
// Very basic helper to extend prototypes of objects
// I'm attaching this method to the Function prototype
// so it'll be available for every function
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype);
}
// Person constructor
function Person(name, age, sex) {
// Common to all Persons
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype = {
// common to all Persons
say: function(words) {
return this.name +'says: '+ words;
}
};
// Student constructor
function Student(name, age, sex, school) {
// Set the variables on the parent object Person
// using Student as a context.
// This is similar to what other laguanges call 'super'
Person.call(this, name, age, sex);
this.school = school; // unique to Student
}
Student.inherits(Person); // inherit the prototype of Person
var mike = new Student('Mike', 25, 'male', 'Downtown'); // create new student
console.log(mike.say('hello world')); //=> "Mike says: hello world"
In newer version of JavaScript (read EcmaScript) they added new ways to deal with objects and extend them. But the concept it's a bit different from classical prototype inheritance, it seems more complicated, and some more knowledge of how JS works underneath would help to really understand how it works, plus it doesn't work in older browsers. That's why I suggest you start with the classical pattern for which you'll find accurate and abundant information on the internet.

Related

What is a JavaScript instance?

What is an instance in JavaScript? Can anyone provide an example please?
Also, please explain your code.
An instance is simply an object that was created by a class (ES6) or constructor function. Here's an example:
function Person(name) {
this.name = name;
}
var john = new Person("John Doe");
console.log(john);
//john is an instance of Person - we can see this by using the instanceof operator
console.log(john instanceof Person);
JavaScript makes instances when defining variables, but these are only accessible by using typeof unless you explicitly use the new constructor to make your variable:
var str = "Foo Bar";
var num = 123;
var bool = true;
var obj = { abc: "def" }
var arr = [true, 1, "s"];
console.log(typeof str);
console.log(typeof num);
console.log(typeof bool);
console.log(typeof obj);
console.log(typeof arr);
console.log(typeof undefined);
console.log(typeof null);
There are a couple of tricks with typeof though - typeof [] == "object" because an array is an object with a few different methods. The other most common issue is typeof null == "object", because of a discrepancy when JavaScript was created between null and undefined.
If you want to find the constructor of any value, use constructor.name:
var str = "Foo Bar";
var num = 123;
var bool = true;
var obj = { abc: "def" }
var arr = [true, 1, "s"];
console.log(str.constructor.name);
console.log(num.constructor.name);
console.log(bool.constructor.name);
console.log(obj.constructor.name);
console.log(arr.constructor.name);
This trick also works with your own constructors and classes:
function Person(name) {
this.name = name;
}
var john = new Person("John Doe");
console.log(john.constructor.name);
When you create an object !
Example:
//instancing a image
var myImage = new Image(100, 100);
//Append in to body
document.querySelector("body").appendChild(myImage);
Simply put, in object-oriented programming, there are classes and objects. When you instantiate, or create an instance of a class, you get an object.
For example, take the following Car class:
function Car(myVin) {
this.vin = myVin;
}
let myHonda = new Car(“24A6733HJ42983C55”);
let myFord = new Car(“JJ67100473KL93228”);
let momsMinivan = new Car(“JF293HJL679904611”);
You just instantiated the Car class three times. Each is an instance.
ES2015 (aka ES6) introduces the class keyword, and constructors:
class Car {
constructor(myVin) {
this.vin = myVin;
}
}
This gets much more involved.
IMO, If you really want to learn OO programming, it’s really best to learn the C++ way first. There you’ll see classical inheritance at work, with concepts of constructors, private, protected, and public data members, design patterns, and other key concepts. This will build a solid foundation before you dive into the kluge that is Ecmascript classical inheritance.
Under the hood, Javascript has prototypical inheritance; Ecmascript plasters classical inheritance on top. It’s is a little weird and hacky, and have to do strange things with closures to achieve privacy.
See link below for a good lesson on OOP in C++.
https://m.youtube.com/watch?v=vz1O9nRyZaY
Let there be an object with properties id, name, and age. Now you want to create 100
objects that represent 100 people. Each person will have an id, name, and age.
You can create objects like:
var person1 = {
id: 1,
name: “p1”,
age: 20
};
var person2 = {
id: 2,
name: “p2”,
age: 21
};
….. And so on.
But instead of creating 100 objects by individually defining id, name, and age for all of
them, you create a standard template with properties id, name, and age. Then use
this template to create objects and set the required values.
This standard template can be seen as an object. Each time you create a new
object by using the new keyword, you create a new instance of an already-defined object with already-specified
properties.
For that, you can do this:
function people(id, name, age){
this.id = id;
this.name = name;
this.age = age;
}
let people1 = new people(1,'rani',20);
let people2 = new people(2,'rahul',21);
let people3 = new people(3,'adi',20);
.
.
.
and so on.
Here people1, people2, and people3 are the instances.

Why is it bad to add properties to prototype of object with __proto__ compared to 'prototype'?

function Person(name, age, height) {
this.name = name,
this.age = age,
this.height = height
}
var john = new Person("John", 24, 175);
What I read should be avoided:
john.__proto__.fact = "I am a humanly human!"
What should be done instead:
Person.prototype.fact = "I am a humanly human!"
If you want to add to the prototype of the object john refers to, doing so through john.__proto__ gives the impression to the reader of the code that this change is specific to john somehow, which it isn't; it affects all objects that use that prototype (current and future). Using Person.prototype doesn't give that impression, it correctly indicates what you're doing.
Separately, note that not all objects (not even all objects with prototypes) have __proto__, because __proto__ is inherited from Object.prototype, but not all objects inherit from Object.prototype. For that reason, in new code, it's best to avoid __proto__ entirely; use Object.getPrototypeOf instead if you need to get the prototype of an object: Object.getPrototypeOf(john).
In a comment you've answered the question of why you'd want to do this with:
To add methods such that they are not present in every Person object you create.
...but that's exactly what adding to john.__proto__ would do: Add the method to every Person object (indirectly through the prototype), current and future, exactly like adding to Person.prototype — because those (and Object.getPrototypeOf(john)) are all just different ways of getting to the same object:
function Person(name) {
this.name = name;
}
var john = new Person("John");
console.log(john.__proto__ === Person.prototype); // true
console.log(Object.getPrototypeOf(john) === Person.prototype); // true
var paul = new Person("Paul");
john.__proto__.someNewMethod = function() {
console.log(this.name);
};
john.someNewMethod(); // "John"
paul.someNewMethod(); // "Paul"
If you want to add a method just to the object john refers to, don't use __proto__ or Person.prototype at all: Just do:
john.niftyMethod = function() { /*....*/ };

Kyle Simpson's OLOO Pattern vs Prototype Design Pattern

Does Kyle Simpson's "OLOO (Objects Linking to Other Objects) Pattern" differ in any way from the the Prototype design pattern? Other than coining it by something that specifically indicates "linking" (the behavior of prototypes) and clarifying that there's no to "copying" happening here (a behavior of classes), what exactly does his pattern introduce?
Here's an example of Kyle's pattern from his book, "You Don't Know JS: this & Object Prototypes":
var Foo = {
init: function(who) {
this.me = who;
},
identify: function() {
return "I am " + this.me;
}
};
var Bar = Object.create(Foo);
Bar.speak = function() {
alert("Hello, " + this.identify() + ".");
};
var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");
b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."
what exactly does his pattern introduce?
OLOO embraces the prototype chain as-is, without needing to layer on other (IMO confusing) semantics to get the linkage.
So, these two snippets have the EXACT same outcome, but get there differently.
Constructor Form:
function Foo() {}
Foo.prototype.y = 11;
function Bar() {}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.z = 31;
var x = new Bar();
x.y + x.z; // 42
OLOO Form:
var FooObj = { y: 11 };
var BarObj = Object.create(FooObj);
BarObj.z = 31;
var x = Object.create(BarObj);
x.y + x.z; // 42
In both snippets, an x object is [[Prototype]]-linked to an object (Bar.prototype or BarObj), which in turn is linked to third object (Foo.prototype or FooObj).
The relationships and delegation are identical between the snippets. The memory usage is identical between the snippets. The ability to create many "children" (aka, many objects like x1 through x1000, etc) is identical between the snippets. The performance of the delegation (x.y and x.z) is identical between the snippets. The object creation performance is slower with OLOO, but sanity checking that reveals that the slower performance is really not an issue.
What I argue OLOO offers is that it's much simpler to just express the objects and directly link them, than to indirectly link them through the constructor/new mechanisms. The latter pretends to be about classes but really is just a terrible syntax for expressing delegation (side note: so is ES6 class syntax!).
OLOO is just cutting out the middle-man.
Here's another comparison of class vs OLOO.
I read Kyle's book, and I found it really informative, particularly the detail about how this is bound.
Pros:
For me, there a couple of big pros of OLOO:
1. Simplicity
OLOO relies on Object.create() to create a new object which is [[prototype]]-linked to another object. You don't have to understand that functions have a prototype property or worry about any of the potential related pitfalls that come from its modification.
2. Cleaner syntax
This is arguable, but I feel the OLOO syntax is (in many cases) neater and more concise than the 'standard' javascript approach, particularly when it comes to polymorphism (super-style calls).
Cons:
I think there is one questionable bit of design (one that actually contributes to point 2 above), and that is to do with shadowing:
In behaviour delegation, we avoid if at all possible naming things the same at different levels of the [[Prototype]] chain.
The idea behind this is that objects have their own more specific functions which then internally delegate to functions lower down the chain. For example, you might have a resource object with a save() function on it which sends a JSON version of the object to the server, but you may also have a clientResource object which has a stripAndSave() function, which first removes properties that shouldn't be sent to the server.
The potential problem is: if someone else comes along and decides to make a specialResource object, not fully aware of the whole prototype chain, they might reasonably* decide to save a timestamp for the last save under a property called save, which shadows the base save() functionality on the resource object two links down the prototype chain:
var resource = {
save: function () {
console.log('Saving');
}
};
var clientResource = Object.create(resource);
clientResource.stripAndSave = function () {
// Do something else, then delegate
console.log('Stripping unwanted properties');
this.save();
};
var specialResource = Object.create( clientResource );
specialResource.timeStampedSave = function () {
// Set the timestamp of the last save
this.save = Date.now();
this.stripAndSave();
};
a = Object.create(clientResource);
b = Object.create(specialResource);
a.stripAndSave(); // "Stripping unwanted properties" & "Saving".
b.timeStampedSave(); // Error!
This is a particularly contrived example, but the point is that specifically not shadowing other properties can lead to some awkward situations and heavy use of a thesaurus!
Perhaps a better illustration of this would be an init method - particularly poignant as OOLO sidesteps constructor type functions. Since every related object will likely need such a function, it may be a tedious exercise to name them appropriately, and the uniqueness may make it difficult to remember which to use.
*Actually it's not particularly reasonable (lastSaved would be much better, but it's just an example.)
The discussion in "You Don't Know JS: this & Object Prototypes" and the presentation of the OLOO is thought-provoking and I have learned a ton going through the book. The merits of the OLOO pattern are well-described in the other answers; however, I have the following pet complaints with it (or am missing something that prevents me from applying it effectively):
1
When a "class" "inherits" another "class" in the classical pattern, the two function can be declared similar syntax ("function declaration" or "function statement"):
function Point(x,y) {
this.x = x;
this.y = y;
};
function Point3D(x,y,z) {
Point.call(this, x,y);
this.z = z;
};
Point3D.prototype = Object.create(Point.prototype);
In contrast, in the OLOO pattern, different syntactical forms used to define the base and the derived objects:
var Point = {
init : function(x,y) {
this.x = x;
this.y = y;
}
};
var Point3D = Object.create(Point);
Point3D.init = function(x,y,z) {
Point.init.call(this, x, y);
this.z = z;
};
As you can see in the example above the base object can be defined using object literal notation, whereas the same notation can't be used for the derived object. This asymmetry bugs me.
2
In the OLOO pattern, creating an object is two steps:
call Object.create
call some custom, non standard method to initialize the object (which you have to remember since it may vary from one object to the next):
var p2a = Object.create(Point);
p2a.init(1,1);
In contrast, in the Prototype pattern you use the standard operator new:
var p2a = new Point(1,1);
3
In the classical pattern I can create "static" utility functions that don't apply directly to an "instant" by assigning them directly to the "class" function (as opposed to its .prototype). E.g. like function square in the below code:
Point.square = function(x) {return x*x;};
Point.prototype.length = function() {
return Math.sqrt(Point.square(this.x)+Point.square(this.y));
};
In contrast, in the OLOO pattern any "static" functions are available (via the [[prototype]] chain) on the object instances too:
var Point = {
init : function(x,y) {
this.x = x;
this.y = y;
},
square: function(x) {return x*x;},
length: function() {return Math.sqrt(Point.square(this.x)+Point.square(this.y));}
};
"I figured to do it makes each obj dependent on the other"
As Kyle explains when two objects are [[Prototype]] linked, they aren't really
dependent on each other; instead they are individual object. You're linking one
object to the other with a [[Prototype]] linkage which you can change anytime you wish. If you take two [[Prototype]] linked objects created through OLOO style as being dependent on each other, you should also think the same about the ones created through constructor calls.
var foo= {},
bar= Object.create(foo),
baz= Object.create(bar);
console.log(Object.getPrototypeOf(foo)) //Object.prototype
console.log(Object.getPrototypeOf(bar)) //foo
console.log(Object.getPrototypeOf(baz)) //bar
Now think for a second do you think of foo bar and baz as being dependent on each-other?
Now let's do the same this constructor style code-
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype= Object.create(Foo);
Baz.prototype= Object.create(Bar);
var foo= new Foo(),
bar= new Bar().
baz= new Baz();
console.log(Object.getPrototypeOf(foo)) //Foo.prototype
console.log(Object.getPrototypeOf(Foo.prototype)) //Object.prototype
console.log(Object.getPrototypeOf(bar)) //Bar.prototype
console.log(Object.getPrototypeOf(Bar.prototype)) //Foo.prototype
console.log(Object.getPrototypeOf(baz)) //Baz.prototype
console.log(Object.getPrototypeOf(Baz.prototype)) //Bar.prototype
The only difference b/w the latter and the former code is that in the latter one
foo, bar, baz bbjects are linked to each-other through arbitrary objects
of their constructor function (Foo.prototype, Bar.prototype, Baz.prototype) but in the former one (OLOO style) they are linked directly. Both ways you're just linking foo, bar, baz with each other, directly in the former one and indirectly in the latter one. But, in both the cases the objects are independent of each-other because it isn't really like an instance of any class which once instantiated, can't be made to inherit from some other class. You can always change which object an object should delegate too.
var anotherObj= {};
Object.setPrototypeOf(foo, anotherObj);
So they're all independent of each-other.
" I was hoping OLOO would solve the issue in which each object knows
nothing about the other."
Yes that's indeed possible-
Let's use Tech as an utility object-
var Tech= {
tag: "technology",
setName= function(name) {
this.name= name;
}
}
create as many objects as you wish linked to Tech-
var html= Object.create(Tech),
css= Object.create(Tech),
js= Object.create(Tech);
Some checking (avoiding console.log)-
html.isPrototypeOf(css); //false
html.isPrototypeOf(js); //false
css.isPrototypeOf(html); //false
css.isPrototypeOf(js); //false
js.isPrototypeOf(html); //false
js.isPrototypwOf(css); //false
Tech.isPrototypeOf(html); //true
Tech.isPrototypeOf(css); //true
Tech.isPrototypeOf(js); //true
Do you think html, css, js objects are connected to each-other? No, they aren't. Now let's see how we could've done that with constructor function-
function Tech() { }
Tech.prototype.tag= "technology";
Tech.prototype.setName= function(name) {
this.name= name;
}
create as many objects as you wish linked to Tech.proptotype-
var html= new Tech(),
css= new Tech(),
js= new Tech();
Some checking (avoiding console.log)-
html.isPrototypeOf(css); //false
html.isPrototypeOf(js); //false
css.isPrototypeOf(html); //false
css.isPrototypeOf(js); //false
js.isPrototypeOf(html); //false
js.isPrototypeOf(css); //false
Tech.prototype.isPrototypeOf(html); //true
Tech.prototype.isPrototypeOf(css); //true
Tech.prototype.isPrototypeOf(js); //true
How do you think these constructor-style Objects (html , css, js)
Objects differ from the OLOO-style code? In fact they serve the same purpose. In OLOO-style one objects delegate to Tech(delegation was set explicitly) while in constructor-style one objects delegate to Tech.prototype(delegation was set implicitly). Ultimately you end up linking the three objects, having no linkage with each-other, to one object, directly using OLOO-style, indirectly using constructor-style.
"As is, ObjB has to be created from ObjA.. Object.create(ObjB) etc"
No, ObjB here is not like an instance (in classical-based languages) of any class
ObjA. It sould be said like objB object is made delegate to ObjA object at it's creation
time". If you used constructor, you would have done the same 'coupling', although indirectly by making use of .prototypes.
#Marcus #bholben
Perhaps we can do something like this.
const Point = {
statics(m) { if (this !== Point) { throw Error(m); }},
create (x, y) {
this.statics();
var P = Object.create(Point);
P.init(x, y);
return P;
},
init(x=0, y=0) {
this.x = x;
this.y = y;
}
};
const Point3D = {
__proto__: Point,
statics(m) { if (this !== Point3D) { throw Error(m); }},
create (x, y, z) {
this.statics();
var P = Object.create(Point3D);
P.init(x, y, z);
return P;
},
init (x=0, y=0, z=0) {
super.init(x, y);
this.z = z;
}
};
Of course, creating a Point3D object that links to the prototype of a Point2D object is kind of silly, but that's beside the point (I wanted to be consistent with your example). Anyways, as far as the complaints go:
The asymmetry can be fixed with ES6's Object.setPrototypeOf or
the more frowned upon __proto__ = ... that I use. We can also use super on regular objects now too, as seen in Point3D.init(). Another way would be to do something like
const Point3D = Object.assign(Object.create(Point), {
...
}
though I don't particularly like the syntax.
We can always just wrap p = Object.create(Point) and then p.init() into a constructor. e.g. Point.create(x,y). Using the code above we can create a Point3D "instance" in the following manner.
var b = Point3D.create(1,2,3);
console.log(b); // { x:1, y:2, z:3 }
console.log(Point.isPrototypeOf(b)); // true
console.log(Point3D.isPrototypeOf(b)) // true
I just came up with this hack to emulate static methods in OLOO. I'm not sure if I like it or not. It requires calling a special property at the top of any "static" methods. For example, I've made the Point.create() method static.
var p = Point.create(1,2);
var q = p.create(4,1); // Error!
Alternatively, with ES6 Symbols you can safely extend Javascript base classes. So you could save yourself some code and define the special property on Object.prototype. For example,
const extendedJS = {};
( function(extension) {
const statics = Symbol('static');
Object.defineProperty(Object.prototype, statics, {
writable: true,
enumerable: false,
configurable: true,
value(obj, message) {
if (this !== obj)
throw Error(message);
}
});
Object.assign(extension, {statics});
})(extendedJS);
const Point = {
create (x, y) {
this[extendedJS.statics](Point);
...
#james emanon - So, you are referring to multiple inheritance (discussed on page 75 in the book "You Don't Know JS: this & Object Prototypes"). And that mechanism we can find in underscore's "extend" function for example. Names of object you stated in your example are a bit mixing apples, oranges and candies but I understand the point behind. From my experience this would be OOLO version:
var ObjA = {
setA: function(a) {
this.a = a;
},
outputA: function() {
console.log("Invoking outputA - A: ", this.a);
}
};
// 'ObjB' links/delegates to 'ObjA'
var ObjB = Object.create( ObjA );
ObjB.setB = function(b) {
this.b = b;
}
ObjB.setA_B = function(a, b) {
this.setA( a ); // This is obvious. 'setA' is not found in 'ObjB' so by prototype chain it's found in 'ObjA'
this.setB( b );
console.log("Invoking setA_B - A: ", this.a, " B: ", this.b);
};
// 'ObjC' links/delegates to 'ObjB'
var ObjC = Object.create( ObjB );
ObjC.setC = function(c) {
this.c = c;
};
ObjC.setA_C = function(a, c) {
this.setA( a ); // Invoking 'setA' that is clearly not in ObjC shows that prototype chaining goes through ObjB all the way to the ObjA
this.setC( c );
console.log("Invoking setA_C - A: ", this.a, " C: ", this.c);
};
ObjC.setA_B_C = function(a, b, c){
this.setA( a ); // Invoking 'setA' that is clearly not in ObjC nor ObjB shows that prototype chaining got all the way to the ObjA
this.setB( b );
this.setC( c );
console.log("Invoking setA_B_C - A: ", this.a, " B: ", this.b, " C: ", this.c);
};
ObjA.setA("A1");
ObjA.outputA(); // Invoking outputA - A: A1
ObjB.setA_B("A2", "B1"); // Invoking setA_B - A: A2 B: B1
ObjC.setA_C("A3", "C1"); // Invoking setA_C - A: A3 C: C1
ObjC.setA_B_C("A4", "B2", "C1"); // Invoking setA_B_C - A: A4 B: B2 C: C1
It is simple example but the point shown is that we are just chaining object together in rather flat structure/formation and still have possibility to use methods and properties from multiple object. We achieve same things as with class/"copying the properties" approach. Summed by Kyle (page 114, "this & Object Prototypes"):
In other words, the actual mechanism, the essence of what’s important
to the functionality we can leverage in JavaScript, is all about objects
being linked to other objects.
I understand that more natural way for you would be to state all the "parent" (careful :) ) objects in one place/function call rather modeling whole chain.
What it requires is shift in thinking and modeling problems in our applications according to that. I'm also getting used to it. Hope it helps and final verdict from the Kyle himself would be great. :)
#Marcus, just like you, I have been keen on OLOO and also dislike the asymmetry as described in your first point. I've been playing with an abstraction to bring the symmetry back. You could create a link() function that is used in place of Object.create(). When used, your code could look something like this...
var Point = {
init : function(x,y) {
this.x = x;
this.y = y;
}
};
var Point3D = link(Point, {
init: function(x,y,z) {
Point.init.call(this, x, y);
this.z = z;
}
});
Remember that Object.create() has a second parameter that can be passed in. Here is the link function that leverages the second parameter. It also allows a little bit of custom configuration...
function link(delegate, props, propsConfig) {
props = props || {};
propsConfig = propsConfig || {};
var obj = {};
Object.keys(props).forEach(function (key) {
obj[key] = {
value: props[key],
enumerable: propsConfig.isEnumerable || true,
writable: propsConfig.isWritable || true,
configurable: propsConfig.isConfigurable || true
};
});
return Object.create(delegate, obj);
}
Of course, I think #Kyle would not endorse shadowing the init() function in the Point3D object. ;-)
Is there a way to OLOO more than "two" objects.. all the examples I consist of the based example (see OP's example). Lets say we had the following objects, how can we create a "fourth" object that has the attributes of the 'other' three? ala...
var Button = {
init: function(name, cost) {
this.buttonName = name;
this.buttonCost = cost;
}
}
var Shoe = {
speed: 100
}
var Bike = {
range: '4 miles'
}
these objects are arbitrary, and could encompass all sorts of behaviors. But the gist is, we have 'n' number of objects, and our new object needs something from all three.
instead of the given examples ala:
var newObj = Object.create(oneSingularObject);
newObj.whatever..
BUT, our newObject = (Button, Bike, Shoe)......
What is the pattern to get this going in OLOO?

In Javascript, the difference between 'Object.create' and 'new'

I think the difference has clicked in my head, but I'd just like to be sure.
On the Douglas Crockford page Prototypal Inheritance in JavaScript, he says
In a prototypal system, objects inherit from objects. JavaScript,
however, lacks an operator that performs that operation. Instead it
has a new operator, such that new f() produces a new object that
inherits from f.prototype.
I didn't really understand what he was trying to say in that sentence so I performed some tests. It seems to me that the key difference is that if I create an object based on another object in a pure prototypal system, then all the parent parent members should be on the prototype of the new object, not on the new object itself.
Here's the test:
var Person = function(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function(){return this.name + ', ' + this.age};
// The old way...
var jim = new Person("Jim",13);
for (n in jim) {
if (jim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output 'name' and 'age'.
// The pure way...
var tim = Object.create(new Person("Tim",14));
for (n in tim) {
if (tim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output nothing because all the members belong to the prototype.
// If I remove the hasOwnProperty check then 'name' and 'age' will be output.
Is my understanding correct that the difference only becomes apparent when testing for members on the object itself?
Your assumptions are correct, but there is another pattern that Douglas doesn't talk much about - the prototype can be used for properties as well. Your person class could have been written as:
var Person = function(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.name = null; //default value if you don't init in ctor
Person.prototype.age = null;
Person.prototype.gender = "male";
Person.prototype.toString = function(){return this.name + ', ' + this.age;};
In this case, iterating over properties of an instance of this class, as you do in your example, would generate no output for the 'gender' property.
EDIT 1:
The assignment of name and age in the constructor do make the properties visible by hasOwnProperty (thanks #matt for reminding me of this). The unassigned gender property would not be visible until someone sets it on the instance.
EDIT 2:
To further add to this, I present an alternative inheritance pattern - one that I have personally used for very large projects:
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superclass = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Person = function(name){
this.name = name;
}
Person.prototype.name = "";
Person.prototype.toString = function(){
return "My name is " + this.name;
}
var OldPerson = function(name, age){
OldPerson.superclass.constructor.call(this);
this.age = age
};
inherits(OldPerson, Person);
OldPerson.prototype.age = 0;
OldPerson.prototype.toString = function(){
var oldString = OldPerson.superclass.toString.call(this);
return oldString + " and my age is " + this.age;
}
This is a fairly common pattern with a small twist - the parent class is attached to the child via the "superclass" property permitting you to access methods/properties overridden by the child. Technically, you could replace OldPerson.superclass with Person, however that is not ideal. If you ever changed OldPerson to inherit from a class other than Person, you would have to update all references to Person as well.
EDIT 3:
Just to bring this full circle, here is a version of the "inherits" function which takes advantage of Object.create and functions exactly the same as I previously described:
var inherits = function(childCtor, parentCtor) {
childCtor.prototype = Object.create(parentCtor.prototype);
childCtor.superclass = parentCtor.prototype;
};
EDIT: This answer was originally a response to #jordancpaul's answer, which he has since corrected. I will leave the portion of my answer that helps explain the important difference between prototype properties and instance properties:
In some cases, properties are shared between all instances and you need to be very careful whenever you're declaring properties on the prototype. Consider this example:
Person.prototype.favoriteColors = []; //Do not do this!
Now, if you create a new Person instance using either Object.create or new, it doesn't work as you might expect...
var jim = new Person("Jim",13);
jim.favoriteColors.push('red');
var tim = new Person("Tim",14);
tim.favoriteColors.push('blue');
console.log(tim.favoriteColors); //outputs an array containing red AND blue!
This doesn't mean you can't ever declare properties on the prototype, but if you do, you and every developer who works on your code needs to be aware of this pitfall. In a case like this, if you prefer declaring properties on the prototype for whatever reason, you could do:
Person.prototype.favoriteColors = null
And initialize it to an empty array in the constructor:
var Person = function(name, age) {
...
this.favoriteColors = [];
}
The general rule when using this method is that default values for simple literal properties (strings, numbers, booleans) can be set on the prototype directly, but any property that inherits from Object (including arrays and dates) should be set to null and then initialized in the constructor.
The safer way is to only declare methods on the prototype, and always declare properties in the constructor.
Anyway, the question was about Object.create...
The first argument passed to Object.create is set as the prototype of the new instance. A better usage would be:
var person = {
initialize: function(name, age) {
this.name = name;
this.age = age;
return this;
},
toString: function() {
return this.name + ', ' + this.age;
}
};
var tim = Object.create(person).initialize("Tim",14);
Now the output will be the same as in your first example.
As you can see, it's a different philosophical approach from the more classical style of OOP in Javascript. With Object.create, the emphasis is on creating new objects from existing objects, rather than on the constructor. Initialization then becomes a separate step.
Personally I have mixed feelings about the Object.create approach; it's very nice for inheritance because of the second parameter that you can use to add additional properties to an existing prototype, but it also is more verbose and makes it so instanceof checks no longer work (the alternative in this example would be to check person.isPrototypeOf(tim)).
The main reason I say Object.create is verbose is because of the second parameter, but there are some useful libraries out there that address that:
https://github.com/Gozala/selfish
https://github.com/Raynos/pd
(and others)
I hope that was more enlightening than confusing!

My dilemma involving JavaScript's Prototypal Inheritance and the hasOwnProperty method

Basically everyone writing about member enumeration in JavaScript heavily advocates the use of the hasOwnProperty method as to avoid going up the prototype-chain.
I understand that this is a form of defensive programming as to prevent iterating over members that are added, for example, to the Object.prototype. But what about the other inherited members? Say, members that are very close in the prototype chain...members that you actually Want to be enumerated over.
Let's say I have the following:
var beget = function (o) { // http://javascript.crockford.com/prototypal.html
function F() {};
F.prototype = o;
return new F();
};
var john = { name: 'john', surname: 'grech' },
mary = beget(john),
p;
mary.age = 42; //augmenting 'mary'
// 'surname' in mary => true
// mary.hasOwnProperty('surname') => false
for (p in mary) {
//skipping over non-direct members, meaning that we also skip members
//inherited from 'john'
if (!mary.hasOwnProperty(p)) {
continue;
}
console.log(p);
}
In the above sample, only age will be displayed, since age is the only direct-member of mary...the other two members, name and surname, are up the prototype chain.
But obviously, I want all the 3 members to be iterated over in the for..in construct; but if you remove the hasOwnProperty, you can then get members from Object.Prototype if someone adds functions to it.
So this is my dilemma.
Do you use prototypal inheritance in combination with the hasOwnProperty method but risk getting members that are too far up the chain during enumeration?
Or do you use the other forms of inheritance that add members directly to the object rather than the prototype?
Hm. You are saying " very close in the prototype chain", but actually, what does it mean very close? Is the three level deep "close" or "far".
Anyway, you could change a bit beget function and implement own hasOwnProperty function for every object, which would go through the prototype chain only till the Object level. This will solve your dilemma of getting members which are added to the Object.prototype by not using hasOwnProperty. Code attached bellow:
var beget = function (o) { // http://javascript.crockford.com/prototypal.html
function F() {
this.hasOwnProperty = function(key) {
return (key != "hasOwnProperty"
&& Object.prototype.hasOwnProperty.call( this, key )
|| o.hasOwnProperty( key )
);
}
};
F.prototype = o;
return new F();
};
var john = { name: 'john', surname: 'grech' },
mary = beget( john ),
p = beget( mary );
mary.age = 42; //augmenting 'mary'
mary.name = "mary";
p.size = "38";
// testing prototype of Object.
Object.prototype.not_own = function(){}
for(var i in p) {
console.debug('Key',i, p.hasOwnProperty(i));
}
// p.hasOwnProperty("size"); // -> true
// p.hasOwnProperty("age"); // -> true
// p.hasOwnProperty("name"); // -> true
// p.hasOwnProperty("not_own"); // -> false
If you need to iterate over the prototypal chain of an object you can use hasOwnProperty to skip direct members (as you said). This will of course also iterate through whichever other member that was added to the prototype of that object (Object.Prototype etc..). There's no way to avoid this.
It's like asking how to avoid enumerating over certain members of a car = {yellow, green, black} object (pseudocode)... you don't... you simply skip certain members based on their value.
Adding members directly to an object isn't really a form of inheritance, unless of course you create objects using the begetObject() technique... because it uses the Prototype to add members.

Categories