I understand the this keyword in javascript. I have used it like this.method() or this.variable =. But what is this(). See the below code:
static fromTX(tx, index) {
return new this().fromTX(tx, index);
}
Please help me understand the use of this() in javascript and in the above code example.
Inside a static method, this will refer to the constructor, so new this() will invoke the constructor:
class Foo {
constructor() {
console.log('making instance');
}
static makeFoo() {
return new this();
}
}
const f = Foo.makeFoo();
Of course, invoking this like that is only possible when this refers to a function, otherwise it'll throw an error. Usually, this will refer to an object, not a function.
Let us take a 2-way approach to the problem:
First, this refers to the current instance within the class and is a keyword in numerous languages.
this() is a call to the constructor and this can contain various parameters as well.
Second, looking at the code snippet, it is a static method- precisely a static factory method. Look it up to understand why and where to use it and more details.
The snippet provides an API to create the class object from params tx, index. You would want to do it to make it more readable for the client who calls this API. It is safe to assume that you might have different APIs too in this method solely for creating an object of the class. Further, in such cases, the constructors are marked private to gain more control over the object instantialtion.
Related
I've recently found an interest in the factory function pattern in JavaScript. Classes may be pretty clean, but I've found they've got their fair share of issues. (I'm not going to even talk about them because that isn't at all the purpose of this question.)
There is one major aspect of factory functions I'm not clear on however.
Correct me if I'm wrong, but in a JavaScript class my methods are placed on the resulting object's prototype so they are only ever created once. This means the constructor function used internally by the class won't be adding the methods as properties to every single new object, meaning conceptually that the methods belong to the class and not the object instance.
class Example {
constructor(message) {
this.message = message;
}
sayMessage() {
console.log(this.message);
}
}
let a = new Example("Hello!");
a.sayMessage(); // Outputs "Hello!"
console.log(Object.getOwnPropertyNames(a));
// Outputs ["message"]
Example.prototype.sayMessage = function() {
console.log(this.message + " Modified!");
};
let b = new Example("Hello!");
b.message = "Goodbye!";
b.sayMessage(); // Outputs "Goodbye! Modified!"
In the class above, sayMessage is the same function for every instance of the class. As demonstrated, it can even be changed on the prototype later, updating all existing instances of the class. I can't say for sure whether I think this is good thing, but it certainly makes sense.
However, in a factory function it seems that the object returned just has all needed methods attached to it as normal properties.
function Example(message) {
let sayMessage = function() {
console.log(this.message);
};
return {
message: message,
sayMessage: sayMessage
};
}
let a = Example("Hello!");
a.sayMessage(); // Outputs "Hello!"
console.log(Object.getOwnPropertyNames(a));
// Outputs ["message", "sayMessage"]
// Modifying the prototype is pointless because
// we haven't explicitly placed any methods there
let b = Example("Hello!");
b.message = "Goodbye!";
b.sayMessage(); // Outputs "Goodbye!"
I'd like to talk about this a bit. So first of all, is avoiding the prototype part of the whole point of using a factory function in the first place? Why would we not create a function once and instead revert to duplicating it across every instance?
I like the idea that I have more control over what I expose in the final object when I use a factory function because I can keep things private in the closure, but can I still use a prototype inheritance sort of model? Or perhaps an even better question: Would I want to? One of the main arguments I found against factory functions is that they are slower than classes in performance critical applications. Well isn't this here part of the reason? Creating a whole bunch of methods for every new object sounds like a huge waste. It sounds like the whole point of having a prototype!
A lot of questions flying around here. Let me boil it all down. I'd like to hear what the rational would be for not using a prototype (or inversely for using one) and if there is a solution that includes the best of both worlds.
Edit: When I first posted the question my second code example was creating Example instances with the new keyword, which was a typo.
Can someone clarify the difference between a constructor function and a factory function in Javascript.
When to use one instead of the other?
The basic difference is that a constructor function is used with the new keyword (which causes JavaScript to automatically create a new object, set this within the function to that object, and return the object):
var objFromConstructor = new ConstructorFunction();
A factory function is called like a "regular" function:
var objFromFactory = factoryFunction();
But for it to be considered a "factory" it would need to return a new instance of some object: you wouldn't call it a "factory" function if it just returned a boolean or something. This does not happen automatically like with new, but it does allow more flexibility for some cases.
In a really simple example the functions referenced above might look something like this:
function ConstructorFunction() {
this.someProp1 = "1";
this.someProp2 = "2";
}
ConstructorFunction.prototype.someMethod = function() { /* whatever */ };
function factoryFunction() {
var obj = {
someProp1 : "1",
someProp2 : "2",
someMethod: function() { /* whatever */ }
};
// other code to manipulate obj in some way here
return obj;
}
Of course you can make factory functions much more complicated than that simple example.
One advantage to factory functions is when the object to be returned could be of several different types depending on some parameter.
Benefits of using constructors
Most books teach you to use constructors and new
this refers to the new object
Some people like the way var myFoo = new Foo(); reads.
Drawbacks
Details of instantiation get leaked into the calling API (via the new requirement), so all callers are tightly coupled to the constructor implementation. If you ever need the additional flexibility of the factory, you'll have to refactor all callers (admittedly the exceptional case, rather than the rule).
Forgetting new is such a common bug, you should strongly consider adding a boilerplate check to ensure that the constructor is called correctly ( if (!(this instanceof Foo)) { return new Foo() } ). EDIT: Since ES6 (ES2015) you can't forget new with a class constructor, or the constructor will throw an error.
If you do the instanceof check, it leaves ambiguity as to whether or not new is required. In my opinion, it shouldn't be. You've effectively short circuited the new requirement, which means you could erase drawback #1. But then you've just got a factory function in all but name, with additional boilerplate, a capital letter, and less flexible this context.
Constructors break the Open / Closed Principle
But my main concern is that it violates the open/closed principle. You start out exporting a constructor, users start using the constructor, then down the road you realize you need the flexibility of a factory, instead (for instance, to switch the implementation to use object pools, or to instantiate across execution contexts, or to have more inheritance flexibility using prototypal OO).
You're stuck, though. You can't make the change without breaking all the code that calls your constructor with new. You can't switch to using object pools for performance gains, for instance.
Also, using constructors gives you a deceptive instanceof that doesn't work across execution contexts, and doesn't work if your constructor prototype gets swapped out. It will also fail if you start out returning this from your constructor, and then switch to exporting an arbitrary object, which you'd have to do to enable factory-like behavior in your constructor.
Benefits of using factories
Less code - no boilerplate required.
You can return any arbitrary object, and use any arbitrary prototype - giving you more flexibility to create various types of objects which implement the same API. For example, a media player that can create instances of both HTML5 and flash players, or an event library which can emit DOM events or web socket events. Factories can also instantiate objects across execution contexts, take advantage of object pools, and allow for more flexible prototypal inheritance models.
You'd never have a need to convert from a factory to a constructor, so refactoring will never be an issue.
No ambiguity about using new. Don't. (It will make this behave badly, see next point).
this behaves as it normally would - so you can use it to access the parent object (for example, inside player.create(), this refers to player, just like any other method invocation would. call and apply also reassign this, as expected. If you store prototypes on the parent object, that can be a great way to dynamically swap out functionality, and enable very flexible polymorphism for your object instantiation.
No ambiguity about whether or not to capitalize. Don't. Lint tools will complain, and then you'll be tempted to try to use new, and then you'll undo the benefit described above.
Some people like the way var myFoo = foo(); or var myFoo = foo.create(); reads.
Drawbacks
new doesn't behave as expected (see above). Solution: don't use it.
this doesn't refer to the new object (instead, if the constructor is invoked with dot notation or square bracket notation, e.g. foo.bar() - this refers to foo - just like every other JavaScript method -- see benefits).
A constructor returns an instance of the class you call it on. A factory function can return anything. You would use a factory function when you need to return arbitrary values or when a class has a large setup process.
A Constructor function example
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
new creates an object prototyped on User.prototype and calls User with the created object as its this value.
new treats an argument expression for its operand as optional:
let user = new User;
would cause new to call User with no arguments.
new returns the object it created, unless the constructor returns an object value, which is returned instead. This is an edge case which for the most part can be ignored.
Pros and Cons
Objects created by constructor functions inherit properties from the constructor's prototype property, and return true using the instanceOf operator on the constructor function.
The above behaviors can fail if you dynamically change the value of the constructor's prototype property after having already used the constructor. Doing so is rare, and it can't be changed if the constructor were created using the class keyword.
Constructor functions can be extended using the extends keyword.
Constructor functions can't return null as an error value. Since it's not an object data type, it is ignored by new.
A Factory function example
function User(name, age) {
return {
name,
age,
}
};
let user = User("Tom", 23);
Here the factory function is called without new. The function is entirely responsible for the direct or indirect use if its arguments and the type of object it returns. In this example it returns a simple [Object object] with some properties set from arguments.
Pros and Cons
Easily hides the implementation complexities of object creation from the caller. This is particularly useful for native code functions in a browser.
The factory function need not always return objects of the same type, and could even return null as an error indicator.
In simple cases, factory functions can be simple in structure and meaning.
Objects returned do not generally inherit from the factory function's prototype property, and return false from instanceOf factoryFunction.
The factory function can't be safely extended using the extends keyword because extended objects would inherit from the factory functions prototype property instead of from the prototype property of the constructor used by the factory function.
Factories are "always" better. When using object orientated languages then
decide on the contract (the methods and what they will do)
Create interfaces that expose those methods (in javascript you don't have interfaces so you need to come up with some way of checking the implementation)
Create a factory that returns an implementation of each interface required.
The implementations (the actual objects created with new) are not exposed to the factory user/consumer. This means that the factory developer can expand and create new implementations as long as he/she doesn't break the contract...and it allows for the factory consumer to just benefit from the new API without having to change their code...if they used new and a "new" implementation comes along then they have to go and change every line which uses "new" to use the "new" implementation...with the factory their code doesn't change...
Factories - better than all anything else - the spring framework is completely built around this idea.
Factories are a layer of abstraction, and like all abstractions they have a.cost in complexity. When encountering a factory based API figuring out what the factory is for a given API can be challenging for the API consumer. With constructors discoverability is trivial.
When deciding between ctors and factories you need to decide if the complexity is justified by the benefit.
Worth noting that Javascript constructors can be arbitrary factories by returning something other than this or undefined. So in js you can get the best of both worlds - discoverable API and object pooling/caching.
I think the factory function is superior to the constructor function. Using new with the constructor function, we are binding our code to one specific way of creating an object, while with a factory, we are free so we can create more different instances without binding ourselves. Let's say we have this class:
const file = new CreateFile(name)
If we want to refactor CreateFile class, creating subclasses for the file format our server supports, we can write an elegan factory function:
function CreateFile(name) {
if (name.match(/\.pdf$/)) {
return new FilePdf(name);
} else if (name.match(/\.txt$/)) {
return new FileTxt(name);
} else if (name.match(/\.md$/)) {
return new FileMd(name);
} else {
throw new Error("Not supprted file type");
}
}
with factory functions, we can implement private variables, hide the information from the users which is called encapsulation.
function createPerson(name) {
const privateInfo = {};
// we create person object
const person = {
setName(name) {
if (!name) {
throw new Error("A person must have a name");
}
privateInfo.name = name;
},
getName() {
return privateInfo.name;
},
};
person.setName(name);
return person;
}
For the differences, Eric Elliott clarified very well,
But for the second question:
When to use one instead of the other?
If you are coming from the object-oriented background, Constructor function looks more natural to you.
this way you shouldn't forget to use new keyword.
Given the documentation
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
I'm currently following a tutorial about creating a blockchain using node.js
https://developers.caffeina.com/chiccocoin-learn-what-is-a-blockchain-by-creating-one-in-nodejs-12929a89208b
But what I don't understand in the following example (code provide by the tutorial I'm following) is why should I bind the keyword 'this' to a method which belong to a class. Given the function newBlock() belong of the class Blockchain, it should have access to the 'this' and all of the variable related to the class Blockchain.
class Blockchain {
constructor () {
this.chain = []
this.newBlock = this.newBlock.bind(this)
this.newBlock(100, 1)
}
newBlock (proof, previousHash) {
const block = this.chain.length + 1
}
}
Does anyone can explain me why should I use bind(this) with a method in a class ? Actually it may be possible that I misunderstood the purpose of bind(this) so that would be great if you could point me out what did I misunderstand.
Thanks :)
Bind will create a copy of the function which will guarantee that the reference of "this" in function newBlock will point to Blockchain. If a new function (let's call it function readBlocks) were to invoke newBlock, it's this context would instead point to readBlocks instead of Blockchain. Binding will allow you to use newBlock without worrying about it's this context being dynamic.
class definition the way you did, in javascript, is still doing prototypal inheritence behind the scenes. This class definition is malleable and you can add more methods to it by just adding more methods to it's prototype. So the class syntax is more like syntactic sugar (not completely, but for most practical purposes) for the normal prototypal inheritence done using functions.
Given that background, this binding in javascript was always done at runtime (except for arrow functions). The context in which a particular method is called determines the this binding. It's not bound at the time of defining the method. But that rule does not hold if you prebind the method to a particular context, like you did in your example with .bind.
If you had not done that, someone could have called the method newBlock like this
let a = new Blockchain()
let b = new Blockchain()
a.newBlock.call(b, proof, previousHash)
And since binding of this is done at runtime, in the above case, the method newBlock will be called with this refering to object b. But that will not happen if you prebind the method using .bind.
It's tricky. But main takeaway is that the runtime binding rules of this in javascript still hold for the new class syntax. Hope it helped.
I often use the pattern of a main JavaScript constructor function and adding methods to its prototype object so they can be called intuitively by the user, for example:
function Slideshow(options) {
this.options = options
this.slideshow = $('#slideshow')
//more variables here
}
Slideshow.method1 = function () {
this.slideshow.addClass('test') // do something with slideshow variable
};
Slideshow.method2 = function () {
// another method
};
The one thing that really bugs me about this pattern is how in order to make variables accessible across all prototype methods, I have to add "this" in front of each variable inside the constructor function. It's a major pain, and I can't help but think there's a more elegant way to do this.
If I forgo using the prototype object and just add the methods as instance methods, I know I can't get around this problem, but I like the efficiency? and self encapsulating nature of this pattern. Any other suggestions for a better pattern? Thanks!
It's a major pain
No, it's really not. Every single JavaScript developer uses this syntax. If you were in Ruby or Python, you'd use self., in PHP you'd use $this->. Some languages like C++ don't require any special decorator, but JavaScript does.
and I can't help but think there's a more elegant way to do this.
No, there isn't.
This is JavaScript's syntax, you cannot change it, and you cannot work around it. If you want to access a property of this, you need this. before the property name. Otherwise, you're talking about global variables.
If you want a different syntax, consider a different language like CoffeeScript, which compiles to JavaScript.
meager has pretty much summed things up if you're talking about accessing public instance properties or methods. You have to use this in front of it as that's just how the language works.
But, if you have private instance properties or methods, you can define those as local variables inside the constructor and you can access them without this.
function slideshow(options) {
// no need to resave the options arguments as they can be used
// directly from the argument variable
// define a per-instance private variable that other methods defined
// within the constructor can use directly without the use of `this`
var theShow = $(options.selector || '#slideshow');
// define public methods
this.method1 = function() {
// can access private instance variable here without this in front of it
theShow.addClass('test');
}
this.method2 = function() {
theShow.addClass(options.decoaration);
}
}
This general design pattern is described here: http://javascript.crockford.com/private.html
Practically speaking, this works because the constructor function with the public methods declared inside it creates a closure that lasts for the duration of the object lifetime so the local variables in the constructor become per-instance variables accessible only from the functions declared within the constructor.
How does one call another object's method in the current method?
Example:
function OjbectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
// How to call Object A's doWork() method
}
Current attempt:
// Call doWork
ObjectA.doWork();
Error: "Type Error: doWork() function is not defined.
Question:
What is the correct way to call the method of another object WITHIN the method. What about scoping?
Does ObjectA have to instantiated to call it's methods?
What about the apply() or call() method? I am confused how they apply in this situation.
Final remarks
I want to thank everyone's input in advance. I have only recently made the dive into javascript's OOP. This seemingly simple question is something that I have been struggling all day and I came on here as a final resort.
What is the correct way to call the method of another object WITHIN the method. What about scoping?
There is no one "correct" way. Presumably you want to be able to call a method of ObjectA instances (i.e. a method of ObjectA.prototype) but have an instance of ObjectB as this, so:
ObjectB.prototype.method = function() {
// How to call Object A's doWork() method
ObjectA.prototype.doWork.call(this);
}
That will call the method and set the instance of ObjectB as this.
Does ObjectA have to instantiated to call it's methods?
If you mean "does and instance of ObjectA have to instantiated to call its methods" then no, as shown above. You can call the method on the constructor's prototype directly.
What about the apply() or call() method? I am confused how they apply in this situation.
See the answer to the first question. Whether to use call or apply depends on the arguments that need to be passed and whether you intend do to any processing on them first.
Additional answers
Could you explain the mechanics of ObjectA.prototype.doWork.call(this) a little more?
It calls the method and sets its this to the supplied object. The rules for how a value is assigned to this are explained in EMCA–2626 §10.4.3.
Would ObjectA.prototype.doWork(this) work just the same way?
No. That calls the function, sets its this to ObjectA.prototype and supplies the value of this from the calling execution context as the first parameter. e.g. if it's global code in a browser, effectively:
ObjectA.prototype.doWork(window);
There is a typo, not ObjectA.doWork(); use objectA.doWork();
There really seems to be some confusion with JavaScript's general OOP model.
Every function has an underlying prototype, which is just an object. You may or may not add anything to it, but if you do, you probably plan to use that function as a constructor. That's what you see happening here:
function ObjectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
objectA.doWork();
However, in some instances, it might be more appealing to just create a function with some methods directly attached to it, rather than creating instances of it. Generally, these would be static methods as in other languages, or perhaps your function is really just a singleton object. In this case, you would omit the prototype, and just attach directly, like so:
function ObjectA() {}
ObjectA.doWork = function () {
alert('do work');
}
ObjectA.doWork()
Going back to the first example, if you define your function and add methods to its prototype, occasionally you may wish to actually call a function that you have defined in a different function's prototype. call and apply can be used to call any function with the value of this changing to the object which you pass into apply or call.
Remember that you are attaching methods to the prototype, so it may look a little funky, but here's an example:
function ObjectA() {}
ObjectA.prototype.doWork = function () {
console.log(this)
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
ObjectA.prototype.doWork.call(this);
}
var objectB = new ObjectB();
objectB.method()
// -> objectB will be logged to your console, bc
// it became the value of this in ObjectA's doWork method.
It's possible to call it from the prototype directly.
Using apply changes the value of this in the execution of the function to the supplied value, so its essentially forwarding this to be itself in the call.
You could also use call, the difference is just in how it takes its arguments, apply takes an array whereas call takes an argument list.
ObjectB.prototype.method = function() {
ObjectA.prototype.doWork.apply(this);
}
However of course an ObjectB does not necessarily have same properties as an ObjectA so make sure you write the method as generic as possible. In order words use a documented concept rather than internal implementation details.
Example again lies with how Array, it's generically applicable methods are documented as such and states what is required for it to work.
In the case you just want to expose a 'utility function', just put it on the object itself. e.g
ObjectA.doWork = function(obj) {
};
After all I found your typo:
function OjbectA() {}
Should be function ObjectA() {}
That's why you were facing error.
function ObjectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
objectA.doWork()
}