"super" keyword cannot access parent property in javascript - javascript

class Base{
constructor(val){
this.val = val;
}
basep = 'default1';
basef(){
return 2;
}
}
class Test1 extends Base{
constructor(val,name){
super(val);
this.name=name;
}
getp(){
console.log(this.name,this.val);
console.log(this.basep); //(in case of proerty) result: 'default1'. if "this" is changed to "super" ===> result: undefined
console.log(super.basef()); //(in case of methods) this and super both work.
}
}
test= new Test1(1,3);
test.getp();
In java 'this' and 'super' worked both fine to get parents property but it seems in javascript only this works.
why is the difference?

In Java, attribute names are put in a scope, and you can have two different attributes with the same name if they were created by different classes. This is not how it works in JavaScript with prototypical inheritance at all, though.
In JavaScript, data properties (that are created by assignment) are owned by the object itself. The parent constructor created the .basep property directly on the child instance. this.hasOwnProperty('basep') will be true.
The super keyword is used to access properties on the parent's .prototype object, regardless of what the current this value is, but still allows calling them on the this object. The basef method lives as a property on Base.prototype, basep does not.

Related

What determines what super.prop refers to in a class?

I'm confused about why exactly super gets set the way it does inside of a class.
In static elements, super.x refers to Parent.x
In methods & field declaration assignments, super.x refers to Parent.prototype.x
MDN says super is either Parent or Parent.prototype, depending on whether the execution context is instance creation or class initialization. To me this makes sense for static elements, where super is seen during class initialization, and for field declarations, where super is seen during instance creation. However, aren't methods evaluated during class initialization, so that they can be put on the class's prototype, and not during instance creation?
aren't methods evaluated during class initialization
No
Methods are not cloned or evaluated, prototype chain is checked when method is not found in instance of the class
class Parent {
doSomething() {}
}
const parent = new Parent()
class Child extends Parent {}
const child = new Child()
console.log(parent.doSomething === child.doSomething)

Class Property in JavaScript

I have a question about class properties. I'll create an example for better understanding. Let's say we have a class.
class Person {}
And we want to add a property. How do we do that? From what I read there are 2 ways:
class Person {myProperty ='Something'} //As shown at https://javascript.info/class. If we use console.log(Person) the property will not show
Now let's create another class that extends Person, let's say Athlete and I want to change myProperty:
class Athlete extends Person{// If we use console.log(Athlete.myProperty ) it will show undefined
myProperty='Something else'// it changes the property
writeSomething() {
console.log(this.myProperty);
}
}
Now let's create a new object using Athlete as constructor
const athlete = new Athlete();
console.log(athlete)// It will have the property myProperty with value 'Something else'
My questions are:
Where is myProperty stored, I can't find it anywhere inside Person or Athlete?
Why can I access myProperty inside writeSomething()?
Why does myProperty appear inside athlete, when it didn't appear anywhere else?
Is this another way of writing properties as opposed to Person.myProperty or is it something else?
Thank you,
Elanvi
First of all, they are not "class properties". They are instance properties just declared upfront. This gives you the clear idea about what fields (properties) can be expected from the class instance.
Based on the documentation:
Public and private field declarations are an experimental feature (stage 3) proposed at TC39, the JavaScript standards committee.
Support in browsers is limited, but the feature can be used through a
build step with systems like Babel.
So, based on the proposal in the link, your code is for declaring public properties of the class instances:
class Person {
myProperty ='Something' // this means anyone can access the property
}
For private properties, they're suggesting this syntax:
class Person {
#myPrivateProperty ='Something' // this means only the instance methods have access
}
To answer your questions:
Where is myProperty stored, I can't find it anywhere inside Person or Athlete?
It's stored as an instance property of an instance of the Person class. Since Athlete extends it, an instance of Athlete also will be given the same property. Read Object Oriented Programming for more details.
Why can I access myProperty inside writeSomething()?
writeSomething() is the method of the instance, so it has access to any instance property. (public and private)
Why does myProperty appear inside athlete, when it didn't appear anywhere else?
It should appear in a Person instance as well. For example, you can write:
const person = new Person();
person.myProperty = 'new Something';
Is this another way of writing properties as opposed to Person.myProperty or is it something else?
It's just a declaration of instance properties made easier and more intuitive, and with implied access modifier (i.e. public).
Finally, if you want to declare a class property, you need to specify it as a static property like this:
class Person {
static myProperty = 'some value';
}
console.log(Person.myProperty);
I'll try to answer your questions as best I can:
Where is myProperty stored, I can't find it anywhere inside Person or Athlete?
Writing:
class Person { myProperty = 'Something' }
Is the same as writing:
class Person {
constructor() {
this.myProperty = 'Something';
}
}
My understanding is that writing it the first way actually adds the property definition to the constructor - you won't see myProperty anywhere on the prototype of Person, the property will not exist anywhere until an instance is created with new Person and the constructor is called.
Why can I access myProperty inside writeSomething()?
You can access myProperty inside writeSomething through the this context as it will refer to the instance of Person unless otherwise bound.
Why does myProperty appear inside athlete, when it didn't appear anywhere else?
The property isn't inside of Athlete per-se but without defining it's own constructor it will inherit the parent class constructor meaning Athlete instances will get the same property defined when they are instantiated. If you were to add a constructor to Athlete you would have to call the super constructor (i.e. Person constructor) at which time the property would be defined on the intstance.
Is this another way of writing properties as opposed to Person.myProperty or is it something else?
As described above, you can also define these instance properties in the constructor with this.myProp = 'my value'. You can read more here on how to use class fields.
Where is myProperty stored, I can't find it anywhere inside Person or
Athlete?
Public instance fields on classes are syntactic sugar for instantiating instance own properties from inside the class constructor.
class Person { constructor() { this.p1 = 'p1 value' } }
Given the following:
class Person { p1 = 'p1 value'; p2 = 'p2 value' }
class Athlete extends Person { p1 = 'p1 overridden value' }
The prototype property of the Person class is placed on to the prototype chain of the prototype property of the Athlete class.
console.log(Athlete.prototype.__proto__ === Person.prototype) // true
The prototype property of the Person class does not contain the p1 property, because it will be dynamically added by the default constructor of the Person class, when an instance is created.
console.log(Person.prototype.hasOwnProperty('p1')) // false
const p = new Person()
When newing-up a Person the constructor dynamically adds the property to the resulting instance.
console.log(p.hasOwnProperty('p1')) // true
const a = new Athlete()
When newing-up an Athlete the Person super constructor is implicitly called against the Athlete instance putting both p1 and p2 on the instance, finally the Athlete constructor is run and p1 is overwritten.
console.log(a.hasOwnProperty('p1')) // true
console.log(a.hasOwnProperty('p2')) // true
console.log(a.p1) // p1 value overridden
Why can I access myProperty inside writeSomething()?
This is just normal this behavior. When invoking a function as a method, the target of the method is the object it was invoked upon. In this case, the instance of Athlete.
1) Where is myProperty stored, I can't find it anywhere inside Person or Athlete?
Variables that can be accessed inside Person or Athlete are called static class variables. You can define them by either doing:
Person.staticProperty = 'Something';
or
class Person {
static staticProperty = 'Something';
}
This variable can be accessed inside your class:
class Person {
static staticProperty = 'Something';
logStaticProperty() {
console.log(Person.staticProperty);
}
}
2) Why can I access myProperty inside writeSomething()?
When you create an instance of a class using new, you can attach variables that are isolated to that single instance. The syntax being used in the constructor attaches the variable to the instance.
3) Why does myProperty appear inside athlete, when it didn't appear anywhere else?
See #2.
4) Is this another way of writing properties as opposed to Person.myProperty or is it something else?
Using the constructor method is functionally equivalent
class Person {
constructor() {
this.myProperty = 'Somethin';
}
}

What is an instance variable in JavaScript?

In a React tutorial video, the instructor said you need to use this.props rather than just props in a React class component because in that case, it's an instance variable. I'm not totally sure what an instance variable is in that context.
I found a lot of questions explaining what an instance variable is in the context of Java and other languages besides JavaScript--in one question (tagged objective-c), someone answered "In object-oriented programming with classes, an instance variable is a variable defined in a class (i.e. a member variable), for which each object of the class has a separate copy. They live in memory for the life of the class."
However, I know ES6 classes are just objects and are syntactical sugar for prototype-based inheritance --would that answer hold true in the case of JS classes?
To understand this thing, you need to know about function expression, lexical environment, prototype inheritance.
'this' keyword refers to the object it belongs to.
let say we have a class like this,
class Hello{
constructor(name){
this.name = name
}
hello(){
console.log(this.name);
}
}
now let's make a new object with the help of this class.
var person = new Hello('Alex')
Now I can do something like this,
person.hello();
This line will return 'Alex';
Now let's console.log(person);
console.log(person)
person ==> {
name : 'Alex'
<prototype> {
constructor: function Hello()
}
}
You will notice that Hello function is not at the top level of the person object. It is at the first prototype level of that object. Everything inside of this prototype will refer to the class or Factory function or
Constructor function that helps to define that person object. In this case, it refers to Hello class.
var person is defined on the global level. so when you call to person.hello() it will check at the top level of that object. If it is not in there, then it will go to the outside environment and try to find out what is this hello() thing. The outer environment of this person object is the global level. hello() function is not at the global level. When javaScript did not find the hello() in the outer environment then it will throw an error that saying hello() is undefined.
When we use 'this' keyword, it will say check on prototypes too. go through all the prototypes until you meet that thing. If it is not in there, then go outer environment and check if it is there.
'this' keyword will refer anything, to the object it belongs to. Also, remember everything in javaScript is an object expect primitive data
An instance variable is just a property of an object, as Felix Kling said.
You can't use props because that's referencing a global or local variable called props. What you want to access is the current value of props for the current component, stored in this.props.
See a jsfiddle: https://jsfiddle.net/vd5ymhcz/1/
An object is an instance of the class that it is created from. And an instance variable is any property defined in the class for that object (typically inside constructor).
Every instance variable is accessible using 'this.' prefix inside any method of the class.

Can instances of a constructor inherit members that are not defined within the prototype bucket?

MDN explains that the instances of a constructor only inherit members within the constructor.prototype property, but not anything outside of it. For example, Object.prototype.watch() will be inherited to its instance, but not Object.keys();.
If I have a constructor as follows:
function Person(name) {
this.name = name;
}
Person.prototype.greeting = function() {
alert("Hi!");
}
the name property is not inside the prototype property, but the greeting() method is. However, if I create an instance as such:
let person1 = new Person("Foo");
person1 is able to access person1.name as well as person1.greeting() both even though the name property is defined outside of the prototype property.
Technically the answer is yes: an instance can inherit from the prototype object property of its constructor, as well as any properties that the prototype object inherits. This is the generalized meaning of the "prototype chain".
In the case of the example given however, the confusion arises in believing name is inherited - it is not.
Objects can have local or "own" properties in addition to inheriting properties from their prototype chain. Ignoring more advanced usage of getters and setters, inherited properties are read only: if you write to them the value written is held in an "own" property created to locally hold the value written - meaning the value written shadows the inherited value without overwriting it in place.
For more information please research how JavaScript inheritance works and in particular what the Object.prototype.hasOwnProperty method does.
The property and name and method greeting both are available to the person1 in different ways.
name is available to person1 because of new operator
greeting is available to person1 because of prototype
When new operator is used it always returns a Object. And object have its own properties. name is the property of Object.

Using the Prototype and Constructor Properties of JS in conjunction

From what i understand,a Prototype object is an object from which other objects inherit properties and methods,and basically it holds a Constructor Property that Refers to or points to the Constructor function that created the Object.Please Consider the Following Code:
function Animal()
{
this.name="no name";
}
function Cat()
{
Animal.Call(this); //Please Explain
this.mood="sleepy";
}
Cat.prototype=new Animal(); //Cat inheriting Animal?
Cat.prototype.constructor=Cat; //Please Explain
Please explain clearly but in details the code lines with comments and the concept of reflection,thanks.
what's the Purpose of Animal.call(this)
It's like calling super() in other programming languages. It calls the parent constructor (Animal) on the just created new object (this). This is also explained in the MDN documentation about .call.
In your example, Animal assigns "no name" to this.name. So after calling Animal.call(this);, this will have a name property with the aforementioned value.
and Cat.prototype.constructor=Cat;
By default, each prototype's constructor property points to the function it belongs to. But since you overwriting the prototype with Cat.prototype=new Animal();, the constructor property points to a different function now. In this case, since new Animal returns an object that inherits from Animal.prototype, Cat.prototype.constructor will point to Animal. To fix that, we assign Cat again.
Strictly speaking this is not necessary since the constructor property is not used in any internal function. However, if your code relies on it, it has to be set to the correct value.

Categories

Resources