why my getter property is directly in my class instance? - javascript

I was testing a getter in my class and I faced a contrast in my implementation and document, based on MDN document a class getter property should be defined inside the instance's prototype
Getter properties are defined on the prototype property of the class and are thus shared by all instances of the class.
so why I can see the getter directly on my instance,
the issue I have with this implementation is, if we assume the getter property is only inside the instance's prototype so why the this is referred to the k not the Kevin.prototype because this in a getter function inherites the object which is located in it based on the MDN document
A function used as getter or setter has its this bound to the object from which the property is being set or gotten.
so in a nutshell, why we have getc directly in our class instance and why the getc value inside the prototype of k is lambo not undefined?
code:
class Kevin {
constructor(x) {
this.age = x;
this.car = "lambo"
}
get getc() {
return this.car;
}
}
const k = new Kevin(3);

Related

cannot understand the Javascript setter and getter lookup in classes

I understand that JavaScript classes are syntactic sugar over prototypes and not works as pure classes in other OOP languages. But the problem here arises is on the getter and setter. When completely leaving getter and setter in the child class, it behaves normally but if I define any one of getter or setter broke these.
For example:
class A {
constructor() {
this.__value = "Default";
}
set value(value) {
console.log("setter called")
this.__value = value;
}
get value() {
console.log("getter called")
return this.__value;
}
}
class B extends A {
}
let b = new B();
b.value = 2;
console.log(b.value);
The above code works fine but if I define getter or setter in the child class the lookup won't go to parent class. I googled about it and found that, it is intentional and is ES standard. Then why when the child class has no methods the lookup reaches the parent class and able to access the getter and setter?
When you access an object property, either to set a value obj.prop = 'val' or to retrieve a value console.log(obj.prop), the engine will try to find that property in the object's prototype chain.
It starts at the instance. In this case, the instance doesn't have any properties, so it continues.
The next object is the instance's internal prototype, which is B.prototype. If B has the property name being looked at, it'll stop there. If there's a setter, and a value was assigned to the property, the setter will be invoked. If there's a getter, and the value being retrieved, the getter will be invoked.
That's it - once a property is found in the prototype chain, it'll stop searching.
If B.prototype didn't have the setter/getter, then the engine would proceed to the next object. The internal prototype of B.prototype is A.prototype. Then, A's setter or getter would be invoked.
It's possible to invoke the superclass's setters/getters from the child, but it looks a bit strange:
class A {
constructor() {
this.__value = "Default";
}
set value(value) {
console.log("setter called")
this.__value = value;
}
get value() {
console.log("getter called")
return this.__value;
}
}
class B extends A {
set value(value) {
console.log('sub setter calling super');
super.value = value;
}
get value() {
console.log('sub getter calling super');
return super.value;
}
}
let b = new B();
b.value = 2;
console.log(b.value);
After googling and lot of code execution I found an answer to my own question,If we define no accessors(getter or setter) in our child class the lookup will proceed towards the parent but if we set any accessor using the get or set descriptor in child class that will invoke the Object.defineProperty method and set the descriptor we mentioned.If we have both setter and getter there is no problem,but if we leave any one that leads to missing of those property in our current object.That's the reason why we get undefined as the undefined property gets undefined value.So literally we have found the value which is undefined thats the main reason we cannot proceed to the parent prototype as value(undefined) found in the current object and the lookup will stop.

What are the difference between adding a property to instance or adding to prototypeproperty?

I have the following class:
class PersonCl {
constructor(fullName, age) {
this.fullName = fullName;
this.age= age;
}
// Instance methods
// Methods will be added to .prototype property
calcAge() {
console.log(2037 - this.birthYear);
}
greet() {
console.log(`Hey ${this.fullName}`);
}
}
now i have lets say two object that were created from the constructor:
const Joe = new PersonCl('Joe',23);
const Larisa = new PersonCl('Larisa',41);
i'm asking what is the difference between:
1.adding the property species into constructor and set it exactly where we set the fullName and age.
or adding the following line outside the class declaration:
PersonCl.prototype.species = "Male";
The "species" property placed on the prototype object will be visible on all instances in most (but not all situations). As soon as your code makes a change to "species":
someInstance.species = "tiger";
then that instance will have a local property "species", and the value of "species" on other instances will not change.
Clearly, when the property is directly added to instances in the constructor, all instances will be similarly initialized (given your sample code) but thereafter changes can still be made on an instance-by-instance basis. The key point is that updating a property value on an object always makes a local, "own" property of that object and does not affect the prototype.
Some methods intended to help work with object properties as a collection, like Object.keys(), only involve "own" properties, which means properties directly associated with an object and not inherited properties.
Prototype is a real object
A lot of objects could have the same prototype
Prototype could have prototype too
When you read object property JS will look for own property first, and if it does not exists, it will look for this property in prototype and in prototype of prototype, etc.

What exactly does a derived class inherit from its base class?

I currently am learning ES6 classes for Javascript and I seem to understand the concept of them but I don't understand what a derived class inherits from its base class. Is it the methods of the class? Is it safe to assume that the methods of a class are properties of said class? In which case, they are part of the prototype and are thus inherited by objects down the prototype chain. And what about the constructor? Are properties defined inside the constructor inherited?
Thank you for your consideration!
Classes are more or less just syntactic sugar for setting up prototype inheritance.
class Derived extends Base {}
is equivalent to
function Derived(...args) {
return Base.apply(this, args);
}
Object.setPrototypeOf(Derived, Base);
Object.setPrototypeOf(Derived.prototype, Base.prototype);
There is some "magic" involved with super and in the future with public and private class fields, but the basic relationship between objects is the same.
Is it safe to assume that the methods of a class are properties of said class? In which case, they are part of the prototype and are thus inherited by objects down the prototype chain.
Yes, methods become properties of the corresponding prototype object, from which all instances inherit. I.e.
class Foo {
bar() {}
}
is equivalent to
function Foo() {}
Foo.prototype.bar = function() {}
And since a "base class'" property object is in the prototype chain of the derived class, all its methods are available to instances of the derived class.
Are properties defined inside the constructor inherited?
"Inherited" is the wrong word here. The properties are created on the instance itself since that's how constructors work.
Consider the process to be like this:
// Create new instance
var newInstance = Object.create(Derived.prototype);
// Call base constructor with `this` set to new instance
Base.apply(newInstance);
// Call derived constructor with `this` set to new instance
Derived.apply(newInstance);
If the base constructor contained something like this.base = 42;, then that property would be directly created on the new instance, since this refers to the new instance.
Note: In reality the exact flow is a bit different due to the fact extending built-in classes such as Array need special treatment but the end result is roughly the same.
You didn't ask about static methods but these are still part of the inheritance. static methods become properties of the constructor function itself.
class Foo {
static bar() {}
}
is equivalent to
function Foo() {}
Foo.bar = function() {}
Because the constructor of the base class becomes the prototype of the constructor of the derived class, all properties defined on the base constructor are available to the derived constructor.
The developer tools in your browser can actually show you all of this:
class Base {
static staticBase() {}
constructor() {
this.base = 42;
}
fromBase() {}
}
class Derived extends Base {
static staticDervied() {}
constructor() {
super(); // necessary since we extend base
this.derived = 21;
}
fromDerived() {}
}
console.dir(Derived);
console.dir(new Derived());
there are a lot of great resource about fundamental es06
example - https://exploringjs.com/es6/ch_classes.html#details-of-subclassing

How exactly does the Backbone.extend function work?

I would like to know how this extend function works in Backbone.js. And please help me with internally what exactly it is doing.
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent constructor.
if (protoProps && _.has(protoProps, "constructor")) {
child = protoProps.constructor;
} else {
child = function() {
return parent.apply(this, arguments);
};
}
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function and add the prototype properties.
child.prototype = _.create(parent.prototype, protoProps);
child.prototype.constructor = child;
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
return child;
};
here why the parent is added to child variable?
extend takes two params protoProps and staticProps. protoProps are properties that will be assigned to the Class prototype so that when you create an instance of the object the object will have that property as part of its prototype chain1. staticProps are props that are not available to objects created from the Class (using new), but are accessible from the class itself, for example, by calling CatClass.defaultMeow.
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
In the discussion below parent is the what we will call the Base Class, the class which prototype we want to extend to the child, which here we will call the Extended Class.
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent constructor.
if (protoProps && _.has(protoProps, "constructor")) {
child = protoProps.constructor;
if protoProps is a function, or has a constructor property (this is the property that is invoked (as a method) whenever you call new on a Class).
} else {
child = function() {
return parent.apply(this, arguments);
};
}
If not, the Extended Class will use the parent's constructor (when you call new it will invoke the parent's constructor method).
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
_.extend(target, src1,...,srcN) an UnderscoreJS method does a shallow copy of the source objects' properties to the target object. Here were copying all of the parents (static) properties and all the properties pass in to the staticProp object (if supplied) to the new Extended Class.
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function and add the prototype properties.
child.prototype = _.create(parent.prototype, protoProps);
This is probably the most important function of the Backbone.extend routine: this is where the Extended Class "inherits" the base Class' prototype chain. For example, if AnimalClass.prototype.walk is a method in the prototype chain for AnimalClass, _.create(parent.prototype, protoProps) will create a new Class with the the walk method in this new Class prototype chain, as well as all the protoProps passed in. This is, in essence, the _extended prototype chain` and it gets assigned to the Extended Class, as it's prototype.
child.prototype.constructor = child;
This is line is confusing at first since we saw in conditional statement above that the Extended Class was already assigned a constructor. Well, it did, but in the last statement, when we did _.create(...) we overwrote the Extended Class' constructor with the Base Class' constructor! Now we're reassigning it.
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
Like the comment says, the Extended Class has access to the Base Class in the ***static property* __super__. It's a convenience property that is accessed from the Extended Class object itself. In our previous example, then, if aCatClass is extended from AnimalClass, then the following is true: CatClass.__super__ === AnimalClass.
return child;
};

Why isn't the function declared in the prototype called?

var p = function () {
this.show = function () {
alert('hello world!!!');
}
}
p.prototype.show = function() {
alert('haha');
}
var o = new p();
o.show();
It alerts "hello world!!!", why?
Can I modify prototype method, if yes how?
That's because the specific function you define in the constructor overrides the one that is inherited through the prototype.
From EcmaScript specification :
Every object created by a constructor has an implicit reference
(called the object’s prototype) to the value of its constructor’s
“prototype” property. Furthermore, a prototype may have a non-null
implicit reference to its prototype, and so on; this is called the
prototype chain. When a reference is made to a property in an object,
that reference is to the property of that name in the first object in
the prototype chain that contains a property of that name. In other
words, first the object mentioned directly is examined for such a
property; if that object contains the named property, that is the
property to which the reference refers; if that object does not
contain the named property, the prototype for that object is examined
next; and so on.
In short : when looking for a function (or any property by its name), you start at the object and then go up in the prototype chain.
You override your prototype.show method in p function.
In Javascript when a property is resolved the engine first looks at the properties of an object. In your example the object would be represented by this. If it finds the property, in this case show (Remember functions can be properties) it uses that property. If the property is not found it then iterates down the prototype chain in an effort to resolve the property.

Categories