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;
};
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've been primarily a Perl coder for years, but also have a background in C++, so I'm coming from a "classical" OO background, and now learning node.js. I just read through The Principles of Object-Oriented JavaScript, which did a good job of explaining the JS concept of OO to classically-minded people like me. But I'm left with a question, specifically related to node.js and inheritance. Pardon me if I'm still using "classical" vocabulary to explain my problem.
Lets suppose I have a module lib/foo.js:
function foo() {
console.log('Foo was called');
}
module.exports.foo = foo;
And I want to "subclass" this in another module lib/bar.js:
var foo = require('foo.js');
// Do some magic here with *.prototype, maybe?
function bar() {
console.log('Bar was called');
}
module.exports.bar = bar;
Such that my main script can do this:
var bar = require('lib/bar.js');
bar.foo(); // Output "Foo was called"
bar.bar(); // Output "Bar was called"
Is this even possible? If so, what am I missing?
Or is this an anti-pattern? Or plain impossible? What should I do instead?
Here's how I did it, to override one method in the request module. Warning: many node modules are poorly designed for extension, including request, as they do way too much stuff in the constructor. Not just a gazillion argument options, but starting up IO, connections, etc. For example, request does the http connection (eventually) as part of the constructor. There is no explicit .call() or .goDoIt() method.
In my example, I wanted to use querystring instead of qs to format forms. My module is cleverly named "MyRequest". In a separate file named myrequest.js you have:
var Request = require('request/request.js');
var querystring = require('querystring');
MyRequest.prototype = Object.create(Request.prototype);
MyRequest.prototype.constructor = MyRequest;
// jury rig the constructor to do "just enough". Don't parse all the gazillion options
// In my case, all I wanted to patch was for a POST request
function MyRequest(options, callbackfn) {
"use strict";
if (callbackfn)
options.callback = callbackfn;
options.method = options.method || 'POST'; // used currently only for posts
Request.prototype.constructor.call(this, options);
// ^^^ this will trigger everything, including the actual http request (icky)
// so at this point you can't change anything more
}
// override form method to use querystring to do the stringify
MyRequest.prototype.form = function (form) {
"use strict";
if (form) {
this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8');
this.body = querystring.stringify(form).toString('utf8');
// note that this.body and this.setHeader are fields/methods inherited from Request, not added in MyRequest.
return this;
}
else
return Request.prototype.form.apply(this, arguments);
};
Then, in your application, instead of
var Request = require("request");
Request(url, function(err, resp, body)
{
// do something here
});
you go
var MyRequest = require("lib/myrequest");
MyRequest(url, function(err, resp, body)
{
// do that same something here
});
I'm not a JavaScript guru so there may be better ways...
For reference, the specific solution I came up with to my sample code problem follows:
In lib/foo.js:
var Foo = function() {}
Foo.prototype.foo = function() {
console.log('Foo was called!');
};
module.exports = new Foo;
In lib/bar.js:
var foo = require('./foo.js');
var Bar = function() {}
Bar.prototype = Object.create(foo.__proto__);
Bar.prototype.constructor = Foo;
Bar.prototype.bar = function() {
console.log('Bar was called!');
};
module.exports = new Bar;
Then in my test script:
var bar = require('lib/bar.js');
bar.foo(); // Output "Foo was called"
bar.bar(); // Output "Bar was called"
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.
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 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