How to set function to class in JS? - javascript

I have a function
function log() {
console.log('something');
}
that I want this object to have:
class Car {
constructor(name) {
this.name = name;
}
log() {
// something
}
}
How can I attach it without repeating the code inside the function?

You can attach the function as a method on the Car prototype, so now it will be available as a method on all instances.
function log() {
console.log('something');
}
class Car {
constructor(name) {
this.name = name;
}
}
Car.prototype.log = log;
const a = new Car("Audi");
const b = new Car("BMW");
a.log();
b.log();

Basically you can do it in three ways;
first way is by using class constructor and passing function in constructor call
function log() {
console.log('something');
}
class Car {
constructor(name,log) {
this.name = name;
this.log = log
}
}
const audi = new Car("name",log);
audi.log();
second way is by simply using equal operator
function log() {
console.log('something');
}
class Car {
constructor(name,log) {
this.name = name;
}
log = log
}
const audi = new Car("some");
audi.log();
Third way is by using prototype
function log() {
console.log('something');
}
class Car {
constructor(name,log) {
this.name = name;
}
}
Car.prototype.log = log;
const audi = new Car("some");
audi.log();

Like this
Either as a member function OR on the prototype
class Car {
constructor(name) {
this.name = name;
}
log = str => console.log(str); // or log = log if log is defined elsewhere
}
const carA = new Car();
carA.log("vroom");
// or
const logger = str => console.log(str);
Car.prototype.logger = logger;
const carB = new Car();
carA.logger("vroom"); // also available to the previous and other Car objects
carB.logger("vroom");

Related

How to invoke the method myFunction to return (name) i've tried many ways but it doesn't work

Below is what am talking about
class User {
constructor(name) {
this.name = name;
}
myFunction() {
return function() {
return this.name;
}
}
}
let kk = new User("kk");
let speak = kk.myFunction();
speak();
I'm getting this error:
Uncaught TypeError: Cannot read property 'name' of undefined
You should use this.name instead, and the function should not return a function
class User {
constructor(name) {
this.name = name;
}
myFunction() {
alert(this.name);
return this.name;
}
}
let user = new User("jj").myFunction();
console.log(user)
EDIT:
The question you edited now is different from the original question you posted. This one needs a currying solution:
class User {
constructor(name) {
this.name = name;
}
myFunction() {
let name = this.name;
return function() {
return name;
}
}
}
let kk = new User("kk");
let speak = kk.myFunction();
console.log(speak());
You can use an arrow function (() => {}) which won't have it's own binding of this, instead the this value of the enclosing lexical scope is used (your class in this case).
class User {
constructor(name) {
this.name = name;
}
myFunction() {
return () => this.name;
}
}
const speak = new User("kk").myFunction();
console.log(speak());

Capture `this` of caller inside class in JavaScript

Consider the following code:
class Abc {
funcAbc() {
console.log(this);
}
}
const abc = new Abc();
class Def {
constructor(func) {
this.func = func;
}
runFunc() {
this.func();
}
}
const def = new Def(abc.funcAbc);
def.runFunc();
I want this to be Abc when runFunc is called, but in the above implementation, this inside runFunc refers to Def. I understand this is happening because runFunc is a member of class Def. But is there any way I can capture 'original this', i.e. point this to Abc inside runFunc?
I cannot do const def = new Def(abc.funcAbc.bind(abc) because the consumer of class should not be bothered about setting the this context.
Note: This is not a theoretical question, it is an actual requirement in the project I am working on. The wrapper class takes in config, a part of which is a function. This function can also be a method on a class instance, using this inside it. Hence I need to preserve original this when calling the function from inside the wrapper class Def.
You are looking for bind() (or one of its variants).
class A {
constructor() {
this.hello = "hello";
}
run() {
console.log(this.hello);
}
}
class B {
constructor(func) {
this.func = func;
}
run() {
this.func();
}
}
const a = new A();
const b = new B(a.run.bind(a));
b.run();
When you bind() a function, it locks what this will be inside the function when the function is run, regardless of how it is invoked.
You could also wrap up the function in a closure:
class A {
constructor() {
this.hello = "hello";
this.run = ((self) => () => console.log(self.hello))(this);
}
}
class B {
constructor(func) {
this.func = func;
}
run() {
this.func();
}
}
const a = new A();
const b = new B(a.run);
b.run();
Or you could use the arrow function syntax. Note, this one requires the Babel class properties transform plugin to work:
class A {
constructor() {
this.hello = "hello";
}
run = () => {
console.log(this.hello);
}
}
class B {
constructor(func) {
this.func = func;
}
run() {
this.func();
}
}
const a = new A();
const b = new B(a.run);
b.run();
Using function.call(thisArg, args...) can set this to what ever you want. i.e., you could do:
class Abc {
func() {
console.log(this);
}
}
const abc = new Abc();
class Def {
constructor(source) {
this.func = source.func;
this.source = source;
}
runFunc() {
this.func.call(this.source);
}
}
const def = new Def(abc);
def.runFunc();
This solution assumes there will be a method on abc that is called func.

Uncaught TypeError: Cannot set property 'getName' of undefined(anonymous function)

<script>
var Employee = new function(name)
{
this.name=name;
}
Employee.prototype.getName = function()
{
return this.name;
}
var PermanenetEmployee = new function(annualsalary)
{
this.annualsalary=annualsalary;
}
var employee = new Employee("rahul");
PermanenetEmployee.prototype = employee;
var pe = new PermanenetEmployee(5001);
document.write(pe.getName());
</script>
i am implementing inheritance in java script. From this code i want to print employee name like "rahul".But i am getting error in this like Uncaught TypeError: Cannot set property 'getName' of undefined(anonymous function).How to resolve this error?
Employee.prototype.getName = function()
{
return this.name;
}
This is the problem:
var Employee = new function(name)
// ------------^^^
{
this.name=name;
}
(And the same for PermanenetEmployee.)
You don't want new there. new calls the function. You want to do that later, as you have when assigning to employee.
Note that the way you're setting up inheritance between them is an anti-pattern. To make PermanenetEmployee correctly "subclass" Employee, do this:
PermanenetEmployee.prototype = Object.create(Employee.prototype);
PermanenetEmployee.prototype.constructor = PermanenetEmployee;
not
var employee = new Employee("rahul");
PermanenetEmployee.prototype = employee;
...and then have PermanenetEmployee accept name and pass it to Employee:
var PermanenetEmployee = function(name, annualsalary) {
Employee.all(this, name); // <====
// ...
};
...or better use, use ES2015 ("ES6") class (transpiling if you need to, for instance with Babel).
Here's a correct setup. I've also fixed the typo in PermanenetEmployee:
var Employee = function(name) {
this.name = name;
};
Employee.prototype.getName = function() {
return this.name;
};
var PermanentEmployee = function(name, annualSalary) {
Employee.call(this, name);
this.annualSalary = annualSalary;
};
// Set up subclass
PermanentEmployee.prototype = Object.create(Employee.prototype);
PermanentEmployee.prototype.constructor = PermanentEmployee.prototype;
PermanentEmployee.prototype.getAnnualSalary = function() {
return this.annualSalary;
};
// Using
var pe = new PermanentEmployee("Rahul", 5001);
console.log(pe.getName());
console.log(pe.getAnnualSalary());
And with ES2015:
class Employee {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class PermanentEmployee extends Employee {
constructor(name, annualSalary) {
super(name);
this.annualSalary = annualSalary;
}
getAnnualSalary() {
return this.annualSalary;
}
}
// Using
var pe = new PermanentEmployee("Rahul", 5001);
console.log(pe.getName());
console.log(pe.getAnnualSalary());
Again, note that you need to transpile if you want to use that syntax in the wild (for now).
There are a couple ways you can get inheritance to work in JS, I am using this pattern.
First declare the base prototype:
Employee = function () {
};
Employee.prototype = {
getName: function () {}
};
And then the prototype that inherits the base:
PermanentEmployee = function () {
Employee.call(this);
};
PermanentEmployee.prototype = Object.create(Employee.prototype);
PermanentEmployee.constructor = PermanentEmployee;
PermanentEmployee.prototype.foo = function() {}

Field, getter and setter with the same name

Could you explain why I get
Uncaught RangeError: Maximum call stack size exceeded
in this example. What's the sequence of actions?
"use strict";
let myClass = class myClass{
constructor(name){
this.name = name;
}
get name() { return this.name; }
set name(name){ this.name = name; }
}
let myObj = new myClass("John");
You're calling the setter from the setter, infinitely looping.
set name(name) {
this.name = name; // <-- ⛔ `this.name` calls the `set`ter again
}
You should use a differently named backing variable of some sort. Unfortunately the "TC39 Private Fields" proposal for JS is not finalized so they will be public, and a naming convention is needed for now.
Here's a modern example:
class Person {
_name = ""; // 'private' by convention, see also: https://github.com/tc39/proposal-class-fields#private-fields
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
constructor(name) {
this.name = name;
}
}
Or following the Question's structure:
"use strict";
let myClass = class myClass {
constructor(name) {
this.name = name;
}
get name() {
return this._name;
}
set name(name) {
this._name = name;
}
}
let myObj = new myClass("John");
console.log(myObj);
To my surprise it's not trivial to have variables private to a class.

JavaScript - What is a singleton class looks like?

I have 2 Obj: I want to know that if they are Singleton?
a.
var OBJ = function () {
}
OBJ.prototype = {
setName : function (name) {
this.name = name;
},
getName : function () {
return this.name;
}
}
b.
var OBJ = {
setName : function (name) {
this.name = name;
},
getName : function () {
return this.name;
}
}
You can check it by creating two instances of class and compare them:
Print( a === b ); // prints: true
if prints true class is singleton
Or you can try this code for SingletonPattern:
function MyClass() {
if ( arguments.callee._singletonInstance )
return arguments.callee._singletonInstance;
arguments.callee._singletonInstance = this;
this.Foo = function() {
// ...
}
}
var a = new MyClass()
var b = MyClass()
Print( a === b ); // prints: true
Best Solution For Singleton Pattern
This will help you How to write a singleton class in javascript
function Cats() {
var names = [];
// Get the instance of the Cats class
// If there's none, instanciate one
var getInstance = function() {
if (!Cats.singletonInstance) {
Cats.singletonInstance = createInstance();
}
return Cats.singletonInstance;
}
// Create an instance of the Cats class
var createInstance = function() {
// Here, you return all public methods and variables
return {
add : function(name) {
names.push(name);
return this.names();
},
names : function() {
return names;
}
}
}
return getInstance();
}
More on http://www.javascriptkata.com/2009/09/30/how-to-write-a-singleton-class-in-javascript/
Also it can be possible duplicate of Javascript: best Singleton pattern and Simplest/Cleanest way to implement singleton in JavaScript?

Categories

Resources