I learned about prototype and proto and i think i understand it but this just doesn't make sense? Can somebody explain to me why accessing directly Object like this doesn't work.
function createObj() {
this.name = 'user';
this.prezime = 'user';
}
var obj1 = new createObj();
createObj.prototype.__proto__.toString = function () {
return 'works';
} //obj1.toString() returns 'works'
createObj.__proto__.__proto__.toString = function () {
return 'this works as well';
} //obj1.toString() returns 'this works as well '
//Then why this doesn't work:
Object.toString = function () {
return true;
}
From my understanding I am directly changing Object object.
So when I do obj1.toString() shouldn't it go to prototype and
then proto inside prototype and find toString() like it does from last two examples?
This is because you're setting a property on the Object constructor, not the Object prototype when you say Object.toString = ....
Trying to understand the difference between prototype and constructor in JavaScript
If you change Object.toString = ... to Object.prototype.toString = ... you get your desired result:
function createObj() {
this.name = 'user';
this.prezime = 'user';
}
var obj1 = new createObj();
createObj.prototype.__proto__.toString = function() {
return 'works';
} //obj1.toString() returns 'works'
console.log(obj1.toString());
createObj.__proto__.__proto__.toString = function() {
return 'this works as well';
}
console.log(obj1.toString());
Object.prototype.toString = function() {
return true;
}
console.log(obj1.toString())
Related
Often, when I create an object in Javascscript, I will do something like this:
function getObj(property) {
return {
property,
displayProp: function() {
console.log(this.property);
}
}
}
let obj = getObj("Hello World!);
I know that the usual way to create a constructor would be as such:
function getObj(property) {
this.property = property;
this.displayProp = function() {
console.log(this.property);
}
}
let obj = new getObj("Hello World!);
Now, my question is, are these two methods equivalent. As far as I can tell, they are the same, and you can also use the 'new' keyword when creating an object using the first case. For me, the first case makes more sense, but it doesn't matter too much to me. Thanks.
The first example is a function that returns a litteral object (which constructor will remain simply "Object").
The second one creates a new constructor.
function getObj(property) {
return {
property,
displayProp: function() {
console.log(this.property);
}
}
}
// this will be useless because the prototype of getObj is not related to the returned object
getObj.prototype.test_prop = "Test prop";
let obj = getObj("Hello World!");
console.log(obj.constructor.name) // Object
console.log(obj.test_prop) // undefined
function Obj(property) {
this.property = property;
this.displayProp = function() {
console.log(this.property);
}
}
Obj.prototype.test_prop = "Test prop";
obj = new Obj("Hello World!");
console.log(obj.constructor.name) // Obj
console.log(obj.test_prop) // Test prop
What am I trying to do is as following:
var Person = function(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
// This will return error;
console.log(Person('John').getName());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
Am I misunderstanding something?
// This will return error;
console.log(Person('John').getName());
it returns an error bcoz Person() by default returns undefined ,but if you use new it will return the newly created object.
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
this works bcoz a new object with __proto__ set to Person.prototype is returned and since there is a getName() on it , it works as expected.
you may use scope safe constructor for your constructor to work without explicit new.
function Person(name) {
if(this instanceof Person) {
this.name = name;
} else {
return new Person(name);
}
}
http://www.mikepackdev.com/blog_posts/9-new-scope-safe-constructors-in-oo-javascript
If you don't want to have the new keyword all over your code (and I can't think of a good reason to want that, you would be basically hiding an important information), you could just do something like:
var pPerson = function(name) {
this.name = name;
};
pPerson.prototype.getName = function () {
return this.name;
};
var Person = function (name) {
return new pPerson(name);
};
You can use Object.create() if you don't want to use the new keyword. Here's an example from MDN:
// Animal properties and method encapsulation
var Animal = {
type: "Invertebrates", // Default value of properties
displayType : function(){ // Method which will display type of Animal
console.log(this.type);
}
}
// Create new animal type called animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates
// Create new animal type called Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes
If you really really hate your self, you can do this
var Person = function(name) {
var This = {};
This.name = name;
//See note
Object.setPrototypeOf(This, arguments.callee.prototype);
return This;
}
Person.prototype.getName = function () {
return this.name;
}
var p = Person('John');
console.log(p.getName());
Note
You absolutely have to read about this.
You can try creating prototype functions as a part of parent function itself.
var Person = function(name) {
this.name = name;
this.get_name = function() {
return this.name;
}
return this;
}
Person.prototype.getName = function() {
return this.name;
}
// This will return error;
console.log(Person('John').get_name());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
I've been reading about JavaScript prototypal inheritance and the prototype property, and I started making a fiddle to understand the concepts better. But I need help understanding why my example isn't working as I thought it would.
In the following example, I'm trying to create a hierarchy where when you create an object, it tells you the name of the parent object. However, my logs always return "object".
One article explained that prototype chaining works so that if a property is not found on the object, the prototype of the parent is checked, and it keeps going up until 'Object', and if not found returns undefined.
Here's a fiddle to go along: http://jsfiddle.net/hqozqd0m/
Object.prototype.cname = 'object';
function plant() {
function parentname() { return this.cname; }
return {
parentname:parentname
}
}
plant.prototype.cname = 'plant';
function tomato() {
function parentname() { return this.cname; }
return {
parentname:parentname
}
}
tomato.prototype = new plant(); // <-- settings it to plant as parent
var p = new plant();
var t = new tomato();
console.log(p.parentname()); //object
console.log(t.parentname()); //object
updated code - same result
Object.prototype.cname = 'object';
function plant() {
this.sayparentname = function() { console.log(cname); };
}
plant.prototype.cname = 'plant';
function tomato() {
this.sayparentname = function() { console.log(cname); };
}
tomato.prototype = new plant();
var p = new plant();
var t = new tomato();
p.sayparentname();
t.sayparentname();
Normally a constructor function will modify the object that new creates, with statements such as this.foo = bar, and not return anything. Then the result of the new expression is the object.
However, if the function returns an object, that object will replace the one that new created; so when you use new plant() you're just getting a plain Object instance back.
To fix your code you just need to make it like this:
function Plant() {
function parentName() { return this.cname; }
this.parentName = parentName;
}
This question isn't a duplicate of Using "Object.create" instead of "new". The thread in question doesn't focus on passing arguments correctly when using Object.create
I am curious as to how I would go about initializing objects using Object.create as opposed to new. Here is my code so far:
function Human(eyes) {
this.eyes = eyes || false;
}
Human.prototype.hasEyes = function() {
return this.eyes;
}
function Male(name) {
this.name = name || "No name";
}
Male.prototype = new Human(true); //passing true to the Human constructor
var Sethen = new Male("Sethen");
console.log(Sethen.hasEyes());
As you can see above, the Male.prototype = new Human(true); creates a new object with true. When the hasEyes() function is run, this logs true as expected.
So, my question is.. using Object.create how would I go about doing this the same way passing a true parameter??
You must call the constructor using Object.call(this) and then pass your arguments.
function Human(eyes, phrase) {
this.eyes = eyes || false;
this.phrase = phrase;
}
Human.prototype.hasEyes = function() {
return this.eyes;
}
Human.prototype.sayPhrase = function() {
return this.phrase;
}
function Male(name) {
Human.call(this, true, "Something to say"); //notice the call and the arguments
this.name = name || "No name";
}
Male.prototype = Object.create(Human.prototype);
var Sethen = new Male("Sethen");
console.log(Sethen.hasEyes());
console.log(Sethen.sayPhrase());
console.log(Object.getOwnPropertyNames(Sethen));
This works and now the object Male has the properties of eyes and phrase
is this give some clue about prototype inheritance model.
const Human = {
constructor: function (eyes) {
this.eyes = eyes || false;
},
hasEyes: function () {
return this.eyes;
}
};
let Male = Object.create(Human);
Male.constructor = function (name) {
this.name = name || "No name";
return Human.constructor.call(this, "true");
};
let Sethen = Object.create(Male);
Sethen.constructor = function() {
return Male.constructor.call(this, 'Sethen');
};
Sethen.constructor();
console.log(Sethen.hasEyes());
console.log(Object.getOwnPropertyNames(Sethen));
Lets say I have this class:
function classA(n){
this.name = n
}
classA.prototype.getName = function(){
return this.name
}
var x = new classA('john')
console.log(x.getName())
My question is: can I group multiple methods inside a namespace? So I would like to do that:
var x = new classA('john')
console.log(x.CONSTANT.getName())
So I would like to call some methods as x.someMethod() and others as x.CONSTANT.otherMethod()
PS: I'm looking for a cross-browser method. Bind is not working in Safari and IE9.
You can do it, for example, via bind. Google es5 shim for implementation of bind in browsers, which don't support it natively.
function MyClass(name) {
this.name = name;
this.CONSTANT.otherMethod = this.CONSTANT.otherMethod.bind(this);
}
MyClass.prototype.CONSTANT = {
otherMethod: function() {
alert(this.name);
}
};
As far as I know a constant is just a property and it can't contain methods, you need to separate your objects and use methods to have the same effect:
function A (id) {
this.id = id;
this.showId = function () { return this.id; }
};
function B (a) {
this.a = a;
this.getA = function () { return this.a; }
}
var a = new A(12);
var b = new B(a);
b.getA().showId();
edit:
You can use a literal object as follow
function B (id) {
this.id = id;
this.CONSTANT = { otherMethod: function () { alert("..."); } };
someMethod = function () { return this.id; }
}
but the literal CONSTANT object can't access B-object methods,
Consider the #kirilloid post to round this.
You can, but you have to be careful because it won't act like you think it will. The this for the method will be the namespace, not the root object.
For example, in x.CONSTANT.getName(), the this object will be x.CONSTANT, and not x.
Here's some sample code which kinda does what you ask (or in jsfiddle):
function MyClass() {}
MyClass.prototype.CONSTANT = {
getName: function() {
alert('Foo');
}
};
var c = new MyClass();
c.CONSTANT.getName();
To make sure the this is right, you need to do much more.
You can use getters/setters (read this article) to achieve this. For example you may define it like this:
classA.prototype.__defineGetter__('CONSTANT', function() {
var that = this;
return {
getName: function() {
return that.name;
}
};
});
Note that holding reference to the object. It will work now
x = new classA('test');
x.CONSTANT.getName();
// result - test