I am trying to override the default toString method for my objects, Here is the code and the problem:
function test (){
this.code = 0;//later on I will set these
this.name = "";
}
test.prototype.toString= function(){
return this.name + "\t"+ this.code +" \t "+this.anotherFunction();
}
console.log (Lion.toString()); //works correct i.e. calls my function
console.log (Lion); //doesn't call my function. Prints { code: 0, name: 'jack' }
doesn't toString get called by default?
Came across this on google before finding an answer I liked, here is what I ended up doing:
You can use inspect and v8(chrome/nodejs) will use that from console.log() calls:
function Foo() {}
Foo.prototype.inspect = function() {
return "[object Foo]";
}
console.log(new Foo());
Not always. Browsers like Chrome allow you to inspect the object (for debugging purpose) via console.log().
Try this:
console.log (''+Lion);
I was interested in how to do this too, once I saw how nicely Immutable.js prints out objects:
var Immutable = require('immutable');
var map = Immutable.Map({ a: 1, b: 2 });
console.log(map); // Map { "a": 1, "b": 2 }
After some source code scanning, I discovered they pull it off by adding both toString and inspect methods to an object's prototype. Here's the basic idea, more or less:
function Map(obj) {
this.obj = obj;
}
Map.prototype.toString = function () {
return 'Map ' + JSON.stringify(this.obj);
}
Map.prototype.inspect = function () {
return this.toString();
}
Having both toString and inspect methods means that the object will get logged out correctly in node (using inspect), and will be correctly formatted as a string if necessary (using toString).
EDIT: This only applies to node, browsers will still log out the object. If you don't want this, first convert it to a string either by calling toString or by concatenating it with another string: console.log('' + map).
No. Adding something to prototype makes it available, but doesn't mean it will be called simply because you create an instance of the object to which it belongs.
For example:
function foo() {
var bar = 123;
}
foo.prototype.show_bar = function() {
console.log(this.bar);
}
var x = new foo(); // does not log anything
x.show_bar(); // logs 123
I think your confusion is thinking that console.log() automatically tries to convert its parameter to a string. It doesn't; it can output arrays, objects, functions, etc.
Related
I am trying to make some modifications to a Node.js app that I forked, what I am trying to do is call a function within another one.
I have attempted a crack at this by simply calling the method as follows but I'm not really that familiar with Node.js so I'm not sure I'm doing it right.
'use strict';
/*
* initalize the class
*/
function MessageBot(bot, user, cache) {
this.bot = bot;
this.user = user;
this.cache = cache;
}
/*
* perform commands
*/
MessageBot.prototype.librarySearch = function(searchText) {
var self = this;
// call SOS function - this is the bit that doesn't work
MessageBot.prototype.callSos(somenumbervar);
}
MessageBot.prototype.callSos = function(number) {
// do something else here
var self = this;
var commandList = self.cache.get('commandList');
}
Remember that this ostensibly inherits the prototype (directly or indirectly). Therefore, you can just do this.callSos(somenumbervar).
If you want to reach the method through the prototype, you have to tell it what this is. With your current code, this in callSos() will be MessageBot.prototype -- certainly not what you want. So you can also do MessageBot.prototype.callSos.call(this, somenumbervar).
Which approach to take depends on how dynamic you want your objects to be. For example, if you want consumers of MessageBot to be able to "override" callSos() by installing their own method, then you should take the first approach (this.callSos()) as it will look up callSos in the object's inheritance chain. This process will only reach the method you've installed on the prototype if the method hasn't been overridden. IMO this is the approach you should take unless you have a very good reason not to.
See this example, which demonstrates how the two approaches differ regarding overriding, while also showing that both work with regards to passing the correct this value (since both methods can retrieve the expected value from this.data):
function ClassA(data) {
this.data = data;
}
ClassA.prototype.foo = function () {
console.log("this.bar() returned: " + this.bar());
console.log("ClassA.prototype.bar.call(this) returned: " + ClassA.prototype.bar.call(this));
};
ClassA.prototype.bar = function () {
return 'in the ClassA prototype, our data is ' + this.data;
};
console.log('--obj1-- (no override)');
var obj1 = new ClassA(3.14);
obj1.foo();
console.log('--obj2-- (override)');
var obj2 = new ClassA(42);
obj2.bar = function () {
return 'in an overriding method, our data is ' + this.data;
};
obj2.foo();
I am new for knockout. I would like to know the differences between these three and which one is best as per latest framework.
Approach 1 (InvoiceTypes): Declaring all variables and methods using comma and finally using return statement to expose public interface methods.
Approach 2 (OrderTypes): It is similar to Approach 1 but used semicolon to differentiate each variable or method.
Apprach 3 (ModelTypes): It is similar to Approach 2 but with out return statement.
Finally specified calling way of start method in each approach in jquery read.
Approach 1
window.Domain = window.Domain || {}
window.Domain.InvoiceTypes = function () {
var types = ko.observableArray(),
getTypes = function() { return types; },
start = function() {
types.push({name:"knockout"});
},
submit = function() {
alert("submit");
};
return {
getTypes: getTypes,
start: start,
submit: submit
};
}();
Approach 2
window.Domain.OrderTypes = function () {
var types = ko.observableArray();
var getTypes = function() { return types; };
var start = function() {
types.push({name:"knockout"});
};
var submit = function() {
alert("submit");
};
return {
getTypes: getTypes,
start: start,
submit: submit
};
}();
Approach 3
window.Domain.ModelTypes = function () {
var self = this;
self.types = ko.observableArray();
self.getTypes = function() { return types; };
self.start = function() {
types.push({name:"knockout"});
};
self.submit = function() {
alert("submit");
};
};
<script type="text/javascript">
$(document).ready(function() {
window.Domain.InvoiceTypes.start();
window.Domain.OrderTypes.start();
var obj = new window.Domain.ModelTypes();
obj.start();
});
</script>
The difference I can see clearly is, single var declaration & return statement and using of self by this keyword.
Please provides your inputs.
Approaches #1 and #2 are akin to static factory methods. Rather than creating an object with the new keyword, you are calling a static "factory" function that creates and returns a new type for you. As for the comma versus semicolon approach, both are valid, but I prefer semicolons over commas. Why? Because javascript is more forgiving with semicolons than with commas. You can omit a semicolon here and there and the script will still run, whereas commas must always be present for the javascript to be correctly parsed. It is also easier to read with semicolons when your script gets larger.
Approach #3 is what most knockout developers do, or should to. Firstly, because you don't need the little () at the end of your function declaration, so it looks more like a class. However, it looks like you have an error in there:
self.start = function() {
//types.push({name:"knockout"}); // types was not declared,
self.types.push({name:"knockout"}); // only self.types was declared
};
... same error here
self.getTypes = function() {
//return types; types was never declared
return self.types;
};
i'm very familiar with the javascript console.log(), and the php_dump() functions that allows us to see what's in a variable, i want to know if there is some function like this in hogan.js that let us inspect the content of a variable.
add some method to your data and include it at the loctation you need to inspect the scope
var data = {
...
// your vars,
...
inspect: function () {
return function () {
console.log(this);
}
}
};
template.render(data);
anywhere you use {{inspect}} it will log the current render context in the console
I slightly modified it to add the function to the data packet that is passed to Hogan in a centralized position, which, in my code, is a function called render().
Thank you for this clever trick.
function render(template, data, destination) {
data.inspect = function() {
return function() {
console.log("inspect:")
console.log(this);
};
};
// localized strings
data.strings = app.strings;
var tmpl = Hogan.compile(template);
var content = tmpl.render(data);
document.querySelector(destination).innerHTML = content;
}
i have a question regarding defining objects in modules.
lets say i have a module:
/*---obj----*/
function A (param){
this.parm=param;
function func(){
//do somthing
}
}
exports.func=func;
/*---file.js----*/
obj=require('obj');
function fileFunc(A){
A.func();//with out this line it works fine
A.param=2;
}
}
for some reason it does not recognize the function in the object A. it recognizes the object A and its different vars, but when it comes to executing the function it gives the msg:
TypeError: Object # has no method 'func'
i tried also to export the function in A by:
exports.A.func=A.func
or
exports.func=func
neither works..
does someone have a clue?
thanx
matti
The function you defined inside of A is local only to that function. What you want is
function A(param) {
this.param = param;
}
A.func = function() {
// do something
};
But if you are treating A as a constructor then you'll want to put that function in A's prototype
A.prototype.func = function() {
// do something
};
I started using backbone.js recently for a game. I used model to create Timer as follows:
var Timer = Backbone.Model.extend({
defaults: {
'hh':00, 'mm':05, 'ss':00
},
initialize: function() {
},
countDownOnce: function() {
// Count down the time by 1 sec
},
run1: function() {
this.countDownOnce();
}
run2: function() {
setInterval(this.countDownOnce, 1000);
}
});
The countDownOnce function, if called directly as in run1, works fine.
But if the function is passed as an argument to some built-in function, say setInterval as in the run2 function, the value of this is lost.
How to propagate this pointer to the built-in functions?
The Backbone docs have a useful section on binding "this".
Basically, Underscore provides a couple of very useful functions, _.bind and _.bindAll, which help you more easily manage 'this's context.
...
initialize: function() {
_.bindAll(this, 'countDownOnce' //, and whatever other functions you want bound)
}),
...
This will make sure that no matter what context it's called from, the 'this' inside countDownOnce refers to your Timer instance.
One way to do this is using call and apply. For example:
run2: function() {
setInterval(this.countDownOnce.call, 1000, this);
}
Also note that passing a closure/function reference with arguments to setTimeout() and setInterval() requires some manual hacks to work correctly in IE.
this is how javascript was designed (pun intended :)
Basically 'this' binds to the current context so if in a function/method call like this:
var Data = function(name) {
this.name = name;
}
var myData = new Data("viky");
would refer to the name element "inside" Data (i.e., myData in this case)
Now if you had the following:
var Data = function(name) {
function morphName(anotherName) {
//and if you call this like this ;)
alert(this.name); //undefined
}
}
the inner function morphName is bound to the 'current' context i.e., the outer function. In javascript everything is an object, including functions. So the outer (anonymous) function doesn't have a member called name! (makes sense?)
In order to do that most people use the following (by convention):
var Data = function(name) {
var that = this; //capture current context. Some prefer self = this;
function morphName(anotherName) {
//then you access name like that ;)
alert(that.name);
}
}
I suggest you read about javascript closures and scopes to understand this and that :D