How do concatenated function calls in JavaScript work? - javascript

I just saw this code example from the crypto-library of node.js and wondered how this kind of "concatenated" function-calls are implemented?
crypto.createHash('sha256').update(password).update(salt).digest('base64');

The return value of one function is an object (probably the original object, this here). A property of that object is another function.
var myObj = {
foo: function() {
alert("foo");
return this;
},
bar: function() {
alert("bar");
return this;
}
};
myObj.foo().bar().bar().foo().bar();

Related

Javascript call one object method after another [duplicate]

This question already has answers here:
How can I chain my method calls?
(5 answers)
Closed 6 years ago.
I have this object:
const Foo = {
bar(x) {
},
baz(x) {
},
}
How can I rewrite this object to be able to call it's methods like this:
Foo.bar(x).baz(y);
instead of calling them like this:
Foo.bar(x);
Foo.baz(y);
Like in the jQuery where you can call one function after another...
$('bac').addClass('x').removeClass('y');
You will have to return the object itself with each function, so as you could call the function on it again (that's also what jQuery does).
const Foo = {
bar(x) {
return this;
},
baz(x) {
return this;
},
}
You should return this at the end of each function. In this context this refers to the Foo object itself.
const Foo = {
bar(x) {
return this;
},
baz(z) {
return this;
}
}
Example:
Foo.bar(x).baz(z);
is executed as:
Foo.bar(x) // <-- returns 'Foo'
.baz(z) // <-- call 'baz' function of 'Foo'
You Should Return The Object Itself From The Method To Call Another Method Again:
const Foo = {
bar(x) {
alert("BAR");
return this;
},
baz(x) {
alert("BAZ");
return this;
},
}
onload = function() {
Foo.bar().baz();
}
This is known as a Fluent API
In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is an implementation of an object oriented API that aims to provide more readable code.
A fluent interface is normally implemented by using method cascading (concretely method chaining)
In this case it is implemented by returning the self-object this:
const foo = {
bar(x) {
console.log("bar")
return this; // here
},
baz(x) {
console.log("baz")
return this; // and here
}
}
foo.bar(10).baz(20);

Why should fix 'this' when return a function?

I read the piece of code in a book,
Function.prototype.before = function(beforefn){
var _self = this;
return function(){
beforefn.apply(this,arguments);
return _self.apply(this,arguments);
}
}
when execute
beforefn.apply(this,arguments);andreturn _self.apply(this,arguments);,I think even without fix 'this' it will get the same result.
function test(){
return function(){
alert(this.foo);
}
}
var o1 = {
foo:"foo",
test:test(),
}
o1.test(); //alert foo
So what is the purpose to fix this of the author?
P.S This is the first time ask question in StackOverflow,forgive my bad English.Thanks
Thanks for noticing my question! I would rewrite like this:
Function.prototype.before = function(beforefn){
var _self = this;
return function(){
beforefn(arguments);
return arguments.callee;
}
}
.apply(this, …) doesn't fix the thisArg - in contrast, it even makes it dynamic, using the current dynamic this from the returned function. Have a look at how well it works:
function test(){
alert(this.foo);
}
var o1 = {
foo: "bar",
test: test.before(function() { console.log(this); })
};
o1.test(); // logs o1, alerts "bar"
o1.test.call({}); // logs the empty object, alerts undefined
You'd only fix the this argument of _self if you didn't pass the current this, as in
Function.prototype.before = function(beforefn){
var fn = this;
return function() {
beforefn.apply(null, arguments);
return fn.apply(null, arguments);
}
}
where o1.test() would not work any more. Of course, apply is still necessary to pass a variable amount of arguments to the function.

What's the difference between these two statements in Javascript?

Is there any difference between these two snippets apart from just pure preference in which you use? As I've seen both used a lot and am not sure how/why they differ other than just preference in terms of readability.
object.foo = function () {
//code
}
foo : function () {
//code
}
This:
object = {
foo : function () {
// code
}
}
is the complete way to write the second statement, meaning you define the function in the initialization of the object.
This code:
object.foo = function () {
//code
}
can be used both as a shorthand, and if you want to declare the function dynamically after the declaration of the object.
They do exactly the same thing in the example you've given, but there are some slight differences which explain why there are seemingly 2 ways to do the same thing.
Take this example...
var obj = {
foo: function() {
// do something
}
};
You can then extend that object like this...
obj.bar = function() {
// do something different
};
But if you did this...
obj = {
bar: function() {
// do something different
}
};
... you would lose the function foo. So one method is for explicitly declaring an object, complete with properties and functions, and the other method can be used for extending an existing object.
Just to be perfectly clear, this is incorrect syntax...
var obj = {
foo = function() { // it should be foo: function() {}
// do something
}
};

How to call the same function repeatedly?

I want to call a function twice but not through the traditional way. A quick example of what I would be looking to do is below:
var myfunc = {
copy: function(message){
console.log(message);
}
}
myfunc.copy('hello').copy('world');
// result 'hello'
// result 'world'
Is this even possible?
Yes, but you should return the correct object:
var myfunc = {
copy: function(message){
console.log(message);
return this;
}
};
myfunc.copy('hello').copy('world');
// hello
// world
This technique is also known as Method chaining.
No, this will fail because .copy() doesn't return anything, so the second .copy() would throw an undefined error.
Try this:
var myfunc = {
copy: function(message){
console.log(message);
return this;
}
}
You need to chain this, You can also look up to jquerys $.fn how they create method chaining simply return this as this object is your myFunc variable and is used again by the next function
var myfunc = {
copy: function(message){
console.log(message);
return this;
}
};
myfunc.copy('hello').copy('world');
As other answers have pointed out, you need to return this in order to be able to call the same or additional functions on the same object.
You can do this a bit more easily (?) via a higher-order function which we will call "chainify", which takes care of returning this for you:
function chainify(fn) {
return function() {
fn.apply(this, arguments);
return this;
};
}
You can chainify your object methods in various ways, but here's one:
var myfunc = {
init: function() {
this.copy = chainify(this.copy);
return this;
},
copy: function(message){
console.log(message);
}
}.init();
This has the minor advantage that each and every method does not need to be cluttered with the return this at the end, and you don't run the risk of forgetting to do so.
It's called method chaining. Here's a blog that talks about this that you should be able to read and use to answer your question.
Basically you will need to use return this; to return the current object so the next method can use it.
// define the class
var Kitten = function() {
this.name = 'Garfield';
this.color = 'brown';
this.gender = 'male';
};
Kitten.prototype.setName = function(name) {
this.name = name;
return this;
};
Method chaining in JavaScript
This is known a Builder design pattern where in you cascade methods. Google it if it helps.

How to create an object in which the object itself is a function?

I have a javascript object from which I created from a constructor.
var obj = new Obj();
It has several functions but I wish to also use it as follows;
obj();
Obj is defined as:
function obj() {
this.blah = function () {
};
}
How can I do this?
It would be easier to have a function you call which returns an arbitrary function that is treated as both an object and a function. Each one would be unique, and you would not need to use new.
function Obj() {
var ret = function(){
console.log('Hello');
};
ret.blah = function () {
console.log('World');
};
return ret;
}
var obj = Obj();
obj();//Hello
obj.blah();//World
You can create properties on function objects. For instance, if you have the function
function foo() {
return "bar";
}
You can set a property on foo.
foo.baz = 42;
So now you can call foo and get the result "bar", and you can access its baz property.
I think you are looking for 'closure' here.
Try:
function MyObject(/* constructor params */) {
//assign properties to 'this'
return function() {
return this; //<== placeholder implementation
}.bind(this);
}
var obj1 = new MyObject();
Now if you do console.log(obj1) you will see function() { [...] } and you will be able to do obj1() to execute your function.
As a bonus in the code above, I also added this binding in the 'closure' as you will need it in most cases that you are doing anything interesting.

Categories