javascript about AOP - javascript

review my code make it print expected result thax
var Obj = (function () {
var b = 'b',
_f = function () {
// print arguments
Array.prototype.push.call(arguments,b);
console.log(arguments,b);
}
return {
f:_f
};
})();
//rewrite Obj.f
Obj.f = function () {
// add parameters dynamically
Array.prototype.push.call(arguments,333);
// it dose not work
Obj.f.apply(Obj.f,arguments);
}
//when I rewrite Obj.f how to make it print result below
// expected result print 111 333 'b'
Obj.f(111);
// expected result print 666 333 'b'
Obj.f(666);
// expected result print 444 333 'b'
Obj.f(444);

If you want the new version of f() to be able to call the original version of f() that was overwritten then you need to save a reference to the original version. Here's one way to do that:
//rewrite Obj.f
Obj.f = (function() {
var originalF = Obj.f;
return function () {
// add parameters dynamically
Array.prototype.push.call(arguments,333);
// Call original:
originalF.apply(this,arguments);
}
})();
That is, use an IIFE to give you some private scope for the originalF variable and then use that variable from within the new function. (This structure is similar to what you were already using to create your Obj in the first place.)
Note also that the first argument to .apply() sets the value of this within the function being called, so you probably just want to pass this through rather than passing Obj.f, so that the original function gets the same this as the new function. (It doesn't actually matter in your specific example, because your function doesn't use this at all, but still for future reference that's the most logical approach.)

Related

Why I am getting different output when accessing inner function in JavaScript?

Here is my code
function first() {
console.log("first")
return function second() { return console.log("second") }
}
let foo = first() // It is outputing "first" once
foo() // Output is "second"
first()() // Output is "first" "second"
What I do not understand is why foo() is giving a different output comparing to first()(). If foo = first(), then I think it should have the same output.
The second question (and less important) is: how can I avoid the output when assigning the variable let foo = first() ?
It's because you are not assigning first to foo when you do first(), you are calling first. When first is called, it logs "first" to the console and then it returns the function second. So foo gets assigned the return value of first which is the function second.
Assigning first to foo
You can assign the function first to foo via normal assignment without calling it:
let foo = first; // now foo === first
Assigning the returned function second to foo
let foo = first(); // note the use of (); now foo === second
Immediately calling the returned function
In the last line, you are doing two things in one line. The first first() (no pun intended) returns the second function (and thereby executes the console.log statement) which is immediately called via () (and executes the other console.log statement). That's why you see it logging "first"and "second".
let foo = first()(); // note the doubled use of (); now, foo === undefined
Whatever are we doing here?
Although it might seem a bit strange at first, the technique of passing and/or returning a function to/from another function is very useful - so much that it has a name: Higher Order Function (or - as I like to call it - HOF).
One pretty common example of a HOF is Array.prototype.map. When you pass a function to .map, it projects the function onto every element in the array and collects the resulting value of each projection into a new array which it finally returns.
A concrete example of a HOF besides .map: Suppose you have to call .split on different input strings that come from different sources but you always want to split the strings on the same character. Create a makeSplitter HOF:
function makeSplitter(splitOn) { // <-- HOF
return function (inputString) { // <-- return value of HOF
return inputString.split(splitOn);
}
}
With this, you can create a general function that splits an input string, say, by slash:
const splitSlashes = makeSplitter(/\//g);
You can think of splitSlashes as if it had been written like so:
const splitSlashes = function (inputString) {
return inputString.split(/\//g);
}
And now you can use that to split various strings that contain slashes into separate parts:
console.log(splitSlashes('08/12/2022')); // logs ['08', '12', '2022']
console.log(splitSlashes('www.example.com/path/to/x/')); // logs ['www.example.com', 'path', 'to', 'x']
If you need another function that - for example - splits a string on ., just use makeSplitter with another argument:
const splitDots = makeSplitter(/\./g);
Output of a function is a value in return statement but not console.log in a function body
function first() {
return function second() { return 'second' }
}
let foo = first() //now a function is in foo variable
foo() // "second"
first()() // "second"
the same output in both cases

Why pass an undefined javascript function parameter?

So I'm learning Javascript and I see this code:
var apple = {//... an object with some properties};
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple});
Where someMethod and a_property_of_apple are valid methods and properties.
My question pertains to the argument, b, of the anonymous function which is not declared or defined anywhere else:
function (b) {return ...
What is going on here? What is b and why is it being used?
Apologies in advance for the basic nature of the question. If someone just wants to drop some focused terms on me to read up on that would be great short of an explanation.
The anonymous function is a callback function being passed to the apple.method() invocation.
apple.method() will invoke that anonymous function at some point during it's execution, ( or pass it to another function ). Whenever it's invoked it will be invoked with an argument that will be available inside the callback. You could call it b, or response, or whatever you want (logical names are best) and be able to use it within the anonymous function.
You should read about Callback functions over at MDN.
EDIT: I will explain the parts to you
var apple = {} This is the definition of an object
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple}); is defining that fruit is equal to the return value of the invocation of apple.someMethod(...)
apple.someMethod(function (b) {return b.a_property_of_apple}); is the invocation of apple.someMethod with function (b) {return b.a_property_of_apple} as the only argument.
The b argument in the anonymous function function (b) {return b.a_property_of_apple} will be passed to it's invocation within the apple.someMethod.
Here is an example snippet.
// define apple
var apple = {
// define method
someMethod: function( callback ) {
var obj = {
a_property_of_apple: "Eat me!" // this will be returned
}
// return the invocation of callback with obj as argument
return callback(obj);
}
}
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple});
console.log(fruit);
EDIT: Ok, going to use something slightly less abstract as an example.
// notice employees being passed to this function
// that is called an argument and is usable inside the function
var orginization = function( employees ) {
// this will take the empoyees argument and assign it to this.employees
// or set this.employees to an empty array if there is no employees argument
this.employees = employees || [ ];
// this is a method ( a method is a function on an object )
// this function takes 3 arguments
this.addEmployee = function( employee ) {
// we use the 3 arguments to push a new object with title, name, and salary
// properties provided by the function arguments
this.employees.push( employee );
}
// this method returns the value stored in this.employees
this.getEmployees = function() {
return this.employees;
}
}
// this is a variable an array of employees only containing 1 employee
// i will use it in the creation of my new orginization
var employess = [
{
title: "CEO",
name: "Enola",
salary: "$$$$$$$"
}
];
// i use the new to create learningInc from originization( employees )
// originization is a constructor function which creates an object
// with methods and properties found on the constructor
var learningInc = new orginization( employess );
// console.log learningInc.getEmployees() an you will see still only the CEO
// works here
console.log( "before newHire: ", learningInc.getEmployees() );
// lets make a newHire
var newHire = {
title: "Peon",
name: "Sadly McFrownFace",
salary: "$"
};
// add the newHire to the employess of learningInc wth out getEmployees() method
learningInc.addEmployee( newHire );
// log the new value of learningInc.getEmployees and you see we now have 2 employees
console.log( "after newHire: ", learningInc.getEmployees() );
Ok now notice this line var learningInc = new orginization( employess );
The employees variable I'm passing to this function as an argument is used in this function var orginization = function( employees ) { ... }.
Hope this help.
My question pertains to the parameter, b, of the anonymous function which is not declared or defined anywhere else: What is going on here?
What is b and why is it being used?
Why you say it is not declared? It is declared right there. Consider this simple JavaScript function:
function doSomething(a, b){
//do something here;
}
In this code, we are creating a function, naming it "doSomething", and declaring two parameters for it a and b. This is how we declare function parameters in JavaScript. Now your example:
function (b) {return ...
is exactly the same, except we didn't give this function a name, which means it is an anonymous function. That's the only difference, but its parameter b is declared right there like any standard function. So there is nothing special going here, it's a standard function parameter and used as such.
There are a couple concepts at work here
Function declarations vs function expressions; you can use function as an operator to define a function, and assign the function to an identifier and pass it around like any normal object
Callbacks; you can pass a function CB into another function A to be called by A (as defined by A)
Passing something without an identifier
Function Declaration
// declare function
function foo(argFoo) {
console.log('foo', argFoo);
}
// invoke function
foo('was declared'); // "foo" "was declared"
Function Expression
// express function
var bar = function (argBar) {
console.log('bar', argBar);
};
// invoke function
bar('was expressed'); // "bar" "was expressed"
Callbacks
function fizz(callback) {
console.log('first I fizz');
callback();
}
function buzz() {
console.log('then I buzz');
}
fizz(buzz);
// "first I fizz"
// "then I buzz"
Passing without an Identifier,
Basically, defining things in-place
// say we have some fn fizzbuzz
function fizzbuzz(foo) {
console.log(foo);
}
// we could pre-define what we want to pass to it
var i = 1;
fizzbuzz(i); // 1
// or we could pass directly
fizzbuzz(1); // 1
// with anything we like
fizzbuzz({some: 'object'}); // {some: "object"}
// even a function
fizzbuzz(function () {}); // function () {}
Maybe if I break down what is happening into more readable code, you can see what is happening.
someMethod is a method that take a function as an argument. This is more easily seen when broken down like below.
It's up to someMethod to determine what they do with that function. In this example, I am executing the function being passed into someMethod and passing it my this context.
var apple = {
name: 'Apple',
someMethod: function(func) {
return func(this);
}
};
function getName (b) {
return b.name;
};
const name = apple.someMethod(getName); // Apple
To your question: b is defined as the first argument to your anonymous function. This is more clearly expressed when the code is broken out above. But you could also express it like this:
const name = apple.someMethod(function(x) { return x.name; }); // Apple
or like this using ES6:
const name = apple.someMethod(x => x.name); // Apple

Returning function object or anonymous object with same attributes

I am unable to comprehend whether the following two styles have any difference, which is more prefferable or are they just visually different.
STYLE 1 - Exporting a anonymous function that returns a javascript object with functions as attributes
module.exports = function(logger,db,config){
return {
getAByB : function(b,cb){
logger.log(b);
cb(undefined,'someting');
},
getName : function(cb){
db.fetch(function(res){
cb(res)
});
}
}
}
STYLE 2 - Exporting a function with attributes (honestly i don't understand why function name is used in return)
module.exports = function Something(logger,db,config){
Something.getAByB = function(b,cb){
logger.log(b);
cb(undefined,'someting');
}
Something.getName = function(cb){
db.fetch(function(res){
cb(res)
});
}
return Something;
}
Also please explain what this 2nd style is trying to achieve.
Both are not the same.
The first will create a new object with the methods and properties you've specified. This will only be accessible as the return value.
var x = module.exports(1, 2, 3); // Object {getAByB: function...
console.log( module.exports.getAByB ); // undefined
module.exports(1, 2, 3).getAByB(4, 5); // works
The second will set all the methods to be chainable calls on the module.exports method itself as well as an instantly-chainable object:
var y = module.exports(1, 2, 3); // function Something...
console.log( module.exports.getAByB ); // function getAByB...
module.exports(1, 2, 3).getAByB(4, 5); // works
Both versions return a function which takes (logger,db,config) arguments, and then returns a value with getAByB and getName methods. However, there are potentially important differences.
The first version returns a brand new object each time. The second version returns a reference to the same object each time, and overwrites the object's methods! Consider the following code (I've assumed that the code examples are a module called "database-connector"):
var databaseConnector = require("database-connector");
var db1Logger = console.log.bind(console, "Db1 log:");
var db1 = ...;
var db1Connection = databaseConnector(db1Logger, db1, {});
var db2Logger = console.log.bind(console, "Db2 log:");
var db2 = ...;
var db2Connection = databaseConnector(db2Logger, db2, {});
With the first version of the module, this will work fine. However, with the second version of the code, db1Connection and db2Connection will both be the same value! If you call db1Connection.getAByB or db1Connection.getName, then db2Logger and db2 will be used instead because db2Connection's initialization overwrote db1Connection's methods.
Another difference is that with the second version of the module, db1Connection and db2Connection are also both equal to the databaseConnector function, and can be called directly to overwrite their methods again. I don't believe that would be a useful feature or was intended.

What is the difference in the following JS syntax?

Following are two ways to define BW.Timer. Can someone tell me what the difference is? I am not certain the first is even valid, but if it is valid, what is different about using the myfunc=(function(){}()) syntax?
BW.Timer = (function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
} ());
And...
BW.Timer = function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
};
The first is the return-value of the immediately-invoked function. The second is a function. It essentially comes down to what the difference is between these:
var f = (function() { return 0; })();
var f = function() { return 0; };
Since the first function is called immediately, the value of 0 is given to the variable f. The first f is not a function. However, the second f we must call in order to get the value:
f(); // 0
It follows that in your example, the first BW.Timer is the object literal itself and the second is a function returning an object literal. You must call the function in order to get to the object:
BW.Timer().Add(x);
Why use the first then?
You might ask yourself why one would use a syntax like a = (function() { return {}; })() instead of a = {}, but there's a good reason. An IIFE (Immeditately-Invoked Function Expression), unlike a regular function allows the emulation of static variables (variables that maintain their value through a single instance). For example:
var module = (function() {
var x = 0;
return { get: function() { return x },
set: function(n) { x = n }
};
})();
The above a text-book example of the Module Pattern. Since the function is called right away, the variable x is instantiated and the return value (the object) is given to module. There's no way we can get to x other than by using the get and set methods provided for us. Therefore, x is static, meaning its variable won't be overridden each time you use module.
module.set(5);
module.get(); // 5
On the other hand, let's see an example where module is declared as a function instead:
// assume module was made as a function
module().set(5);
module().get(); // 0
When we call module() the x variable is overridden each time. So we're effectively using different instances of module and x each time we call module.
The difference is rather large.
In the first case, BW.Timer is executed when it is first encountered, and that is the static version assigned to BW.Timer. In that instance, BW.Timer.Add(1) may be used. Each call to BW.Timer will be the same object.
In the second case, BW.Timer is not executed when first encountered, and instead is a function referece which must be invoked BW.Timer(). For Add to be used, this must be the case BW.Timer().Add(1). Also, you can issue var timer = new BM.Timer();. Each instance of BW.Timer() will be unique here.
In the first example BW.Timer references an object that the self-executing function returns, while in the second example it references a function object, in other words it's a function that can be executed BW.Timer().

Binding function to another function in object

I try to bind a function but I dont really know how its work
For example
q={};
q.e=function(){return 1;}
q.e.i=function(){alert(this);}
q.e().i(); //Nothing happend I excepted that it will alert 1
So how does it work?
Thank you.
A function does also inherit from Object in Javascript. Hence you can assign properties to a function object, which you're just doing by calling
q.e.i = function() {};
but thats it. If you want to call it, you need to the same semantics
q.e.i();
in your current snippet, you're trying to execute .i() on the return value of e(), which happens to be the number 1.
You should be getting an error when calling q.e().i(); q.e() == 1 so (1).i() is an error since the Number object doesn't have an i method.
Hard to help since the code doesn't make any sense. I can only say that what you expected doesn't make sense in my head :)
Here's some code that would do what you expect
var q = {};
q.e = function() { return 1; };
q.e.i = function() { alert(this); }
// Call q.e.i, specifying what to use as this
q.e.i.call(q.e());
The trick is that in JS, this changes depending on how you call the function.
function a() {
console.log(this);
}
var obj = {
method: a
};
// Outputs the window object, calling a function without a `.` passes
// The window object as `this`
a();
// Outputs the obj, when you say obj.method(), method is called with obj as `this`
obj.method();
// You can also force the this parameter (to the number 1 in this case)
// outputs 1
obj.method.call(1);

Categories