nodejs: short alias for process.stdout.write - javascript

I'm learning nodejs (and I like it!). I tried to figure out how to have shorter alias for console.log and I found out that I can use var cout=console.log and use cout('[string]') from then on. Then when I wanted to use process.stdout.write and I tried to make a short alias for it too, using var out=process.stdout.write. But when I use out('[string]'), I get the following error:
_stream_writable.js:220   var state = this._writableState;
                  ^   TypeError: Cannot read property '_writableState' of undefined
    at Writable.write (_stream_writable.js:220:19)
    at Socket.write (net.js:670:40)
    at Object. (/home/shayan/Desktop/nodejs/server.js:12:1)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:423:7)
What is wrong here?
How can I correctly create a short alias for process.stdout.write?
Thanks

You should not do this kind of "short alias". It's very messy and people reading your code won't understand why you use random function names instead of console.log. However, if you really want to create function aliases, consider using a function:
function out(text) {
// ^ ^- argument accepted by the function
// |------ the function name
process.stdout.write(text)
// ^- pass the argument you accepted in your new function to the long function
}
I added some explanation in case you don't know how a function works, you can safely remove it.
Edit:
The reason why it's not working is in the source code of Node.JS. The stacktrace you are getting back points to this line:
Writable.prototype.write = function(chunk, encoding, cb) {
var state = this._writableState;
// ...
}
It tries to reference a variable called _writableState from this. As written here:
Inside a function, the value of this depends on how the function is called.
This means, that this refers to process.stdout when you call process.stdout.write, however it is undefined, when you call it from your alias. Therefore you get a Cannot read property '_writableState' of undefined exception (as undefined does not contain that variable, which is important for the write function to execute).

Aside from a function declaration you can also use Function.prototype.bind:
const out = process.stdout.write.bind(process.stdout);
out('foo');
bind returns a new function with the context (this) bound to whatever value you pass.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

Related

Function assignment doesn't work

I'm new to Node.js. I have searched the forum but couldn't find a similar question. Here is the problem I encountered. The following code runs fine.
process.stdout.write("hello world!\n");
but the following code:
var myprint = process.stdout.write;
myprint("hello world");
will generate the following error:
TypeError: Cannot read property 'defaultEncoding' of undefined
Any suggestions? Thank you so much.
Probably, the write() method needs to be called with the correct object reference so the write() method knows what stream it is writing to. There are multiple ways to work around this. Here's one way:
var myprint = process.stdout.write.bind(process.stdout);
myprint("hello world");
See .bind() on MDN for more info.
For future reference, when you do:
var myprint = process.stdout.write;
myprint only contains a reference to the write method and that method is then called with no object reference. That means that the this pointer inside the write() method will not point at the stdout stream like it would when you call it as process.stdout.write(). If a method needs it's instance data (which most methods do), then this creates a problem. You can "bind" the object reference to a new temporary function using .bind() which allows you to assign it to another variable and then use it directly like you were attempting to do.
The write function is trying to access a variable on the this variable, which is not set to process.stdout when you call myprint, unlike when you call process.stdout.write.
Note that
var out = process.stdout;
out.print('wow\n');
will work as expected.

checking properties of arguments passed to function we spyOn

I'm trying to figure out (not successfully yet) if it's possible to check if js function I'm trying to mock with spyOn (jasmine) was called with the exact parameters I expected, for example consider function:
foo = function(date, array) {};
So far I can only make sure that the array was indeed passed like this:
spyOn(bar, 'foo').and.returnValue(somePromise.promise);
somePromise.resolve;
//call some function that calls 'foo' eventually...
expect(bar.foo).toHaveBeenCalledWith('10/12/2100', []);
I need to check if the array passed to this function was empty, how can I achieve this? Also if it's possible, how can I check if array passed to this function contained the string I wanted?
Thanks!
Replace and.returnValue with and.callFake, then pass in a function that stores the arguments before returning the promise. Then the arguments can be used for later expect tests.
I don't know Jasmine, so this will probably not be the answer you're looking for.
On the other hand, it is a doable work around that you can implement in the mean time while you await your real answer.
If you have control over foo, then in the foo method you can tell it to set a global variable to its input parameter:
var fooParam;
var foo = function(array){
fooParam = array;
}
Then in your other code, you can do:
if (fooParam != null){
if (fooParam.contains(yourString)){
//I'm not sure if "contains" is actually a method or not,
//but that's really a separate issue.
}
}
So you set the global variable fooParam in the foo method and then you can use it later to do checking.
So there's a potential problem in that you might not have control over foo, such as if it's a system method. To work around that, replace all calls to foo with something like foo2, which you would define to have the same parameters and all it does is call foo and set the global variable. But if you have control of foo, then you don't need to do this.
The other potential problem is that foo will be called multiple times (such as if it's called within a loop). To circumvent this, you might make the global variable be an array list and have foo add its parameters to the array list instead of setting the variable. But if it's not called within a loop, or not called multiple times before it can be processed, then you don't need to do this.
I hope this helps while you're looking for the real answer

Javascript Module Design

I was wondering if someone could explain the difference between these two JavaScript modules. I have been trying to learn how to design javascript modules by reading some underscore.js and jQuery source code, amongst others and have noticed these two patterns.
Example 1
(function() {
var _this = this;
_this.VERSION = '0.1';
}).call(this);
Example 2
(function(_this) {
_this.VERSION = '0.1';
}(this));
call(obj[, arg[, arg[, arg[, ...]]]]) runs function in obj context, function () {}(obj) will run function in current context passing obj in arguments. In this particular example there is no difference - both examples will do same thing. For some people it is just cleaner to run anonymous function with call or apply instead of just () and I think here it is the case.
In second example line with var _this = _this; is useless, _this is already defined within scope and that line is redefining already existing variable with same value (so its even incorrect).
Example 1 explicitly sets the value of the this variable within the function.
In Example 2 the function does not care about the value of this. It rather expects an argument that it can work with. You also could say that it does not rely on the value of this. An advantage of this pattern is that by the name of the parameter it can be made clear what you want (window, myObjectContext ...).
In your specific case it does not make a difference. But if the function contained code that made actual use of this, e.g. this.myObject = {}, it could make a difference, because this could have a different value in each case. But to be true, someone using the second pattern would never reference this within the function.

use this.argu to store arguments a good practice?

i am new to front-end developing,and now i am reading a lot of js code written by other in my company and find they will use this syntax to store the arguments :
function func1(argu1,argu2){
this.argu1 = argu1;
this.argu2 = argu2;
// other code run here....
}
for me i usually skip this and use the argument directly in my code or get a variable for the n,like this:
function func2(argu1,argu2){
alert(argu1);
alert(argu2);
var arguOne = argu1,arguSec = argu2;
// other code run here...
}
so i want want to ask why use this syntax to store an arguments?
is this a good practice ?and why?
Have i ever miss some concepts that i should know?
see the fiddle, written by the my co-worker who has been no longer a front-ender....
In your first example, func1 can be used to create objects. It is effectively a class definition (constructor). It can be used as follows:
function func1(argu1,argu2)
{
this.argu1 = argu1;
this.argu2 = argu2;
}
var instance = new func1('a', 'b');
alert(instance.argu1);
alert(instance.argu2);
Lordy lord: Instead of defining the function, and calling it at the end, try using a closure. Just keep the function definition as is, but put it in brackets:
(function new_slider (arguments)
{
//your code here
})('#new_slider',1500,150,10);
This way, the function is declared, and invoked at the same time, all functions defined within the main new_slider function will have access to the arguments. There is absolutely no reason to use this.argu1 to store these values. If anything, it creates global variables, which is considered bad practice.
Please google closures in JavaScript, they're extremely powerful

JQuery\Javascript - Passing a function as a variable

I was just curious if I could pass a function as a variable. For example:
I have a function
$('#validate').makeFloat({x:671,y:70,limitY:700});
I would like to do something like this:
$('#validate').makeFloat({x:function(){ return $("#tabs").offset().left+$("#tabs").width();},y:70,limitY:700});
This does not work, but ideally every time the variable was accessed it would compute the new value. So if the window was resized it would automatically adjust as opposed to a variable passed in being static. I realize I can implement this directly inside the function\widget, but I was wondering if there was some way to do something like the above.
The concept of this is independent of the plugin. I am talking about the function being "cast" as a variable.
Yes, you can pass an object which will invoke some function when its property is read (this is called a getter), but it is not cross-browser compatible. For example, this will (probably) work in IE9:
var o = {y:70, limitY:700};
Object.defineProperty(o, 'x', {get: function() {return 671;}});
$('#validate').makeFloat(o);
There are other syntaxes for other browsers such as __defineGetter__ for Firefox, and some browsers don't have this functionality at all. So it is practically useless unless you can fully control the environment where your code runs.
This won't work unless x is invoked (obj.x(), instead of just obj.x).
To make it work, the makeFloat() code must check the type of x, and if it's a function, invoke it.
I see what you're trying to do, but it won't work. Why? makeFloat expects the value to be non-function type. It probably uses that value directly. To actually execute the function, makeFloat needs to do x() or even x.call(...) or x.apply(...), which it most certainly isn't doing.
To answer your other question i.e., can you pass functions as variables, the answer is yes. In fact, this is the way callbacks and closures are handled in Javascript. For example, in jQuery when you bind an event handler you are passing in a function as a parameter:
jQuery("#myInputId").click(function() {
...
...
});
Another way that parameters are passed in are as object attributes, for example in jQuery.ajax:
jQuery.ajax({
...
success: function(data) {
},
...
});
In both cases, click and ajax both understand and expect the parameter to be a function and not just a regular variable. For example, assuming you had an object that maintained a list of integers and you had a method called addElement(int), which expected an int parameter, you wouldn't pass in a String. It works the same way in Javascript, except for the fact that the language is not strongly typed. This is why you don't really get a type-mismatch error unless the function explicitly checks the type and throws an exception. This is generally a good practice in such language; I try to do this in the Javascript code that I write.
I've done this with string variables. You'll need to exploit the toString function.
function RefString(fn) { this.toString = function() { return String(fn()); }; }
You can use it like so:
$("#someDiv").somePlugin({optionValue: new RefString(MyFunc), ... });
function MyFunc() {
return new Date().getYear().toString();
}
It works by setting optionValue to a new OBJECT, not necessarily a function. Then anything that reads this object will ask for a value, which by default is the result of the toString function. We simply override the default behavior by executing a function that is specified when the object is constructed.
I'm not sure how it will work for EVERY plugin, but it works when a string or number is expected.
How do you mean "doesn't work"?
It looks like it should compile and run. But what happens is it executes the function and sets the value no different than if you used a constant, or called a function that wasn't inline.
What you need to do is put this line of code in an event that fires when the window is re-sized.
It looks like makeFloat is from a jQuery plugin - are you sure that the plugin is aware that 'x' can be a function and will execute it properly? From the jQuery site, it looks like it only is able to comprehend a number value or 'current' as a string, not a function.
You can pass functions as variables, yes - but that's not actually what you're asking.
What it looks like your asking is "can I set a DOM property to the result of an expression?" to which the answer is "no". (Note - not outside of browser-specific behavior such as IE's CSS Expressions - which have been deprecated in IE8 anyway)
You'll need to bind an event handler to window.onresize and use a function to update the sizing yourself.
In order for a function to be executed from a variable, it has to be called, like so:
$.option.callback.call();
Where option is the containing variable, callback is the function and call executes the function.
It's not like you don't have options though. You can set it up so that the returned value of that function is executed from the line itself. Or you can set it up in the alternative manner that you described.
You need to invoke that function so that it returns the actual value you're looking for. So you're not actually passing in a function, you're invoking it and it's immediately returning a value. For example:
$('#validate').makeFloat({
x:function(){
return $("#tabs").offset().left+$("#tabs").width();
}(),
y:70,
limitY:700
});
Notice the extra () after the function call. This invokes the function immediately, thus returning the value you're looking for.
Note that x doesn't "compute new value" when is accessed (read), but when the function is called, i.e. x(). As Chad mentioned, this is how you can automatically execute a function when windows is resized:
$(window).resize(function() {
// do something
});
[Update] After re-reading your question, I think you may be thinking overcomplicated – isn't this what you are looking for?
$('#validate').makeFloat({
x: $("#tabs").offset().left + $("#tabs").width(),
y: 70,
limitY: 700
});

Categories

Resources