Change constructor's value with another function JS - javascript

I am working on the below task and can't find the solution. I have the constructor (Tree) and object created using it (theTree). Now I want to add new function (alter) that would change greeting value of the constructor (so of all new objects created with it) but also for existing objects. To be honest, I don't know how to get to the contructor's properties within that function. I will appreciate if you could take a look and advise where to start. This is what I got so far:
function Tree(name) {
this.name = name;
this.greeting = "Hi";
}
var theTree = new Tree("Pine");
theTree.greeting = "hello";
var alter = function(constructor, greeting) {
this.greeting = greeting;
}

Put greeting on the prototype. Remove this.greeting = from the constructor, and change the body of alter to constructor.prototype.greeting = greeting;.
However, this will not change the greeting value of instances on which it has already been set directly. No-one knows what instances have been created, unless you keep track of them yourself somehow.

var alter = function(tmpObject,greeting){
tmpObject.greeting = greeting;
console.log(tmpObject.greeting);
}
To alter function pass your constructor and greeting message.It will change.

Related

Setting prototype of a function as prototype of another function for doing Subclassing (with Object.setPrototypeOf()))

I'm not sure if the Title actually made any sense but however I'm trying to set a functions prototype to "sub classes" prototype.
For coming example;
What I try to do is : I have a user and paidUser . paidUser is subclass ofuser
User Factory function :
function userCreator(name, score) {
this.name = name;
this.score = score;
}
userCreator.prototype.sayName = function(){console.log("hi");}
userCreator.prototype.increment = function(){this.score++;}
And I can create a new user with new keyword. so far so good.
const user1 = new userCreator("Phil", 5);
Now , coming to Subclassing . (accountBalance is just a silly property special for paidUser for my example)
function paidUserCreator(paidName, paidScore, accountBalance){
userCreator.call(this, paidName, paidScore);
this.accountBalance = accountBalance;
}
now I want to set prototype of my userCreator as the prototype of paidUserCreator Factory Function
The following line works perfectly, but I don't understand it quite. Object.create function is supposed to created an empty object and that empty objects __proto__ must be the given parameter.
paidUserCreator.prototype =Object.create(userCreator.prototype);
paidUserCreator.prototype.increaseBalance = function(){
this.accountBalance++;
}
Another point what I don't understand is :
Why the following line doesn't work ?
Object.setPrototypeOf(paidUserCreator, userCreator.prototype);
For completion :
const paidUser1 = new paidUserCreator("Katarina", 4, 12);
PS: Yes I know the Class keyword is much cleaner and nicer to read but I want to learn how to do it in this way.
Starting with the last question:
Why the following line doesn't work ?
Object.setPrototypeOf(paidUserCreator, userCreator.prototype);
It will, but you need to set the prototype of paidUserCreator.prototype not the function paidUserCreator so that when an instance looks for something on the paidUserCreator.prototype and doesn't find it, it will look to userCreator.prototype.
function userCreator(name, score) {
this.name = name;
}
userCreator.prototype.sayName = function() {
console.log("hi");
}
function paidUserCreator(paidName, paidScore, accountBalance) {
userCreator.call(this, paidName, paidScore);
}
Object.setPrototypeOf(paidUserCreator.prototype, userCreator.prototype);
let p = new paidUserCreator("Mark", 98, 200.5)
p.sayName()
paidUserCreator.prototype = Object.create(userCreator.prototype) is similar. Object.create makes a new object and sets it's prototype to point to the object passed in. When you do this you are replacing paidUserCreator.prototype with a new object that is prototype linked to userCreator.prototype. One caveat with this is that if there is anything on paidUserCreator.prototype that you need it will be lost because you are replacing the whole object, not just setting the prototype.
Here's an example where that might bite you:
function userCreator(name, score) {
this.name = name;
}
userCreator.prototype.sayName = function(){console.log("hi");}
function paidUserCreator(paidName, paidScore, accountBalance){
userCreator.call(this, paidName, paidScore);
}
// points to the paidUserCreator function
console.log(paidUserCreator.prototype.constructor)
// replace protoype with new object
paidUserCreator.prototype = Object.create(userCreator.prototype);
// now paidUserCreator.prototype has no constructor property
// so it defers to paidUserCreator
console.log(paidUserCreator.prototype.constructor)

JavaScript Function Get Object

Is there a way for a function to get the object value before the function name? Below is an example of what I am kinda trying to achieve. I want to be able to read the myElement variable within the function but not pass it as a parameter but pass it before the function with the dot.
Any simple examples or explanations would be most helpful.
var myElement = document.getElementById('myID');
myElement.myFunction();
function myFunction() {
alert(myElement);
}
The only way you could do this is to add myFunction to HTMLElements prototype (which is what gets returned by document.getElementById(). That's usually frowned upon, but if it's your own project and you know what you do, you could do that.
var myElement = document.getElementById('myID');
HTMLElement.prototype.myFunction = function() {
console.log(this);
}
myElement.myFunction();
<div id="myID"></div>
With this prototype in place, you can call myFunction on every HTMLElement in your code.
In regards to your last comment, the function could be
HTMLElement.prototype.myFunction = function() {
alert(this.id);
}
I don't see why you should do it, as it's much easier to just do
alert(myElement.id);
In regards to the comments, here's what I'd do. Instead of extending anything, create your own class (or function), that takes a HTMLElement. Now on this class, you can add whatever method you want, manipulate your element and then return the plain HTMLElement from a getter. You can obviously change that to whatever return you want.
class MyHtmlElement {
constructor(htmlElement) {
this._htmlElement = htmlElement;
}
alertId() {
alert(this._htmlElement.id);
// optional
return this;
}
logId() {
console.log(this._htmlElement.id);
// optional
return this;
}
setId(newId) {
this.htmlElement.id = newId;
// optional
return this;
}
setStyle(prop, val) {
this._htmlElement.style[prop] = val;
// optional
return this;
}
get htmlElement() {
return this._htmlElement;
}
set htmlElement(value) {
this._htmlElement = value;
}
}
const el = new MyHtmlElement(document.getElementById('foo'));
el
.setId('bar')
.logId()
.alertId()
.setStyle('background-color', 'red')
.setStyle('width', '100vw')
.setStyle('height', '100vh');
// If you need the plain element, return it
const plainHTMLElement = el.htmlElement;
console.log(plainHTMLElement);
<div id="foo"></div>
When a function is stored in an object and then called with theObject.theFunction(), the value of this within the function will be theObject.
function sayHello() {
alert('Hello, my name is ' + this.name);
}
let myObject = { name: 'Bob', speak: sayHello };
myObject.speak(); // shows the message 'Hello, my name is Bob'
Now if you want to be able to create your own function and let it be used by an Element, you either need to store the function in the Element instance first or to add it to the Element prototype, both of which I highly discourage. If you feel like you have to do this, there's a flaw in your design.
Still, if you have a good reason to add a custom method to an existing object, I recommend you look up lessons about prototype inheritance in JavaScript, or read my old answer about it here if you're not sure how it works. You could say, make a function which adds methods to an object when it is called, like this:
function addMethods(elem) {
elem.speak = sayHello;
}
let myElement = document.getElementById('myID');
addMethods(myElement);
myElement.speak(); // Hello, my name is <value of the element's name attribute>
Or you could add the method to the prototype of all elements:
Element.prototype.speak = sayHello;
let myElement = document.getElementById('myID');
myElement.speak();
While browsers have let people do this since forever ago, there is technically no guarantee that Element is publicly available, or that its prototype is modifiable, or that you can add methods to Element instances. The Prototype framework (an inconveniently named third party library) has been using these techniques for a long time, but it did cause them a couple issues. jQuery prefers using a different approach, wrapping elements in another object on which custom methods are put.

I'm changing the constructor of a javascript class, but the new constructor isn't called?

I'm using SAP UI5 Framework. I'm creating an instance of a class and then changing the constructor of a class. While creating the second instance of the class, new constrctor isn't called!
var myConstructor = function(){
alert('my own constructor');
}
var btn = new sap.m.Button({text:'Hello World'}) //sap.m.Button is a class
sap.m.Button.prototype.constructor = myConstructor; //Changing the constrcutor
var btn2 = new sap.m.Button({text:'h'}); // why myConstructor aint called !
Here is the working example http://jsbin.com/voluc/2/edit
Thanks
You're not actually changing the constructor by doing this
sap.m.Button.prototype.constructor = myConstructor;
You're simply changing a property that is used by the prototype to refer back to it's constructor function.
To completely change the constructor you simply need to re-assign it
sap.m.Button = myConstructor;
Still I don't know why you would do that. If you want to temporarily change the constructor then you might want to store it first and then set it back to it's initial version.
var oldCtor = sap.m.Button;
sap.m.Button = = myConstructor;
// finished doing your tasks
sap.m.Button = oldCtor;
Changing default constructor can affects on object behaviour so don't do that things.
<script>
var myConstructor = function(){
alert('my own constructor');
}
var btn = new sap.m.Button({text:'Hello World'})
btn.placeAt('content');
sap.m.Button = myConstructor; //Changing the constrcutor
var btn2 = new sap.m.Button({text:'h'}); // why myConstructor ain't called !
console.log(sap.m.Button.constructor)
//but if you see i doh't write btn2.placeAt("content") because of your constructor don't do many things as need
</script>

JavaScript Inherited Properties Default Value

Consider having below code
function Employee() {
this.id = "";
this.name = "";
this.gender = "";
}
function Programmer() {
this.expertise = "";
}
Programmer.prototype = new Employee();
And then I want to inherit the Programmer further to JScriptProgrammer with default value of "expertise" set to "JavaScript".
Question:
What is the diference between
function JScriptProgrammer() {
this.expertise = "JavaScript";
}
JScriptProgrammer.prototype = new Programmer();
and
function JScriptProgrammer() {
}
JScriptProgrammer.prototype = new Programmer();
JScriptProgrammer.prototype.expertise = "JavaScript";
You can use prototype for default values of an object and it does save memory. If you don't surely shadow the property later (assign a new value for it on the instance) then all instances share the same pointer to the value.
If however you are surely going to assign a value to it then better define it in the constructor body as this.myval
Here is the tricky part of assigning default values to prototype; you have to re assign a new value to it to make an instance specific change. Object values can be manipulated by invoking functions on them or re assigning properties. When you do that then the default value for all instances change:
var Person=function(){};
Person.prototype.teeth=[0,1,2,3];
Person.prototype.legs={left:1,right:1};
var ben=new Person();
var betty=new Person();
ben.teeth.splice(2,1);//ben looses a tooth
//when ben looses a tooth like that betty looses it too
console.log(betty.teeth);//[1,2,3] poor betty
//now poor betty has an accident
betty.legs.right=0;
//looks like ben looses it too
console.log(ben.legs);//{left:1,right:0}
//I don't feel sorry for ben though because
//he knocked out betty's tooth
It is better not to initiate a new instance for inheritance, you can use Object.create or a helper function to set up inheritance without creating an instance. All about inheritance, prototype, overriding and calling super here:https://stackoverflow.com/a/16063711/1641941
the difference
function JScriptProgrammer() {
this.expertise = "JavaScript";
}
JScriptProgrammer.prototype = new Programmer();
Means when you are using JScriptProgrammer() the expertise value are already been set to "JavaScript"
but when you use
function JScriptProgrammer()
{
}
JScriptProgrammer.prototype = new Programmer();
JScriptProgrammer.prototype.expertise = "JavaScript";
Means you set expertise value after using JScriptProgrammer()
They are the same. Second version saves memory, meaning all the children use the same instance of the function/variable.
See following example which shows why this might be required
function JScriptProgrammer() {
var tmp = "Hello";
//accessing private variables
this.sayHello = function() {
alert(tmp + " "+ this.expertise + "er");
}
}
JScriptProgrammer.prototype = new Programmer();
JScriptProgrammer.prototype.expertise = "JavaScript";
More reading
Use of 'prototype' vs. 'this' in JavaScript?
Declaring javascript object method in constructor function vs. in prototype
How to set the prototype of a JavaScript object that has already been instantiated?
In resumen:
prototype is use to inherit of existing object. For example. If you want to add a new method to Array object you can do this
Array.prototype.MyNewMethod = function()
{
alert("im bellow to array object")
}
Which means that you can to this
var array = [1,2,3];
array.MyNewMethod();//prints im bellow to array object
(read this post for more reference)
Which means that your code is doing this:
function JScriptProgrammer() {
}
function Programmer(){
this.name = "hello world";
}
JScriptProgrammer.prototype = new Programmer();// inhering from Programmers object(or lets say class)
JScriptProgrammer.prototype.expertise = "JavaScript"; // assigning a value to expertise property that belows to JScriptProgrammer class
console.log(new JScriptProgrammer())//JScriptProgrammer {name: "hello world", expertise: "JavaScript"} notice that property name that bellow to Programmer
object now is in JScriptProgrammer object as well.
here test http://jsbin.com/IgOFimi/1/edit

How to do encapsulation in javascript

can you please tell me how to do encapsulation in javascript .I have a class Name Car .I want to extend this class with B class .Secondly I want to override and overload the methods in java script.
Here is my fiddle
http://jsfiddle.net/naveennsit/fJGrA/
//Define the Car class
function Car() { }
Car.prototype.speed= 'Car Speed';
Car.prototype.setSpeed = function(speed) {
this.speed = speed;
alert("Car speed changed");
}
//Define the Ferrari class
function Ferrari() { }
Ferrari.prototype = new Car();
// correct the constructor pointer because it points to Car
Ferrari.prototype.constructor = Ferrari;
// replace the setSpeed method
Ferrari.prototype.setSpeed = function(speed) {
this.speed = speed;
alert("Ferrari speed changed");
}
var car = new Ferrari();
car.setSpeed();
can you explain these two lines
Ferrari.prototype = new Car();
This line show Ferrari is extend by car ?
Ferrari.prototype.constructor = Ferrari;
what is the used of this line ?
JS, by design does not provide a built-in way to manage the visibility of members of an object. but its flexible enough to allow us to do encapsulation.
Effective write up i found for you is http://www.codeproject.com/Articles/108786/Encapsulation-in-JavaScript
Ferrari.prototype = new Car()
This method adds Car poperties to the Ferrari's prototype. Whatever is returned by the Car(), is added to the existing Ferrari's prototype.
Ferrari.prototype.constructor = Ferrari
Prototype has a constructor property which is overriden by this call Ferrari.prototype = new Car(). This is manually resetting it again.
prototype and constructor object properties
I have edited your fiddle. http://jsfiddle.net/fJGrA/3/
Using closure in javascript you can hide elements within an object or function.
function foo(args){
//this is a private variable.
var _name = ""
return{
getname:function(){
return _name
}
}
}
bar = new foo()
// name can only be accessed from inside the foo function.
Whenever a variable is created with a var keyword within a function, it is accessible only in the scope of that function. Effectively, being private to it.

Categories