I am new to JS and fully excited about its capability to behave both as a functional & OO language.
I want to create an object Eg: MyString which behaves like the native String() constructor function.
When I call String('name') on the chrome console, I get 'name'.
When I call var s = new String('sname'); I get an object instance.
Similarly I tried doing the same
function MyString(val){
this.toString1 = function(){ return " " + val; }
return val;
}
When I call MyString('name'), I get 'name'
When I call var ms = new MyString('sname'); I get an object which exposes a toString1() method (just like the native String()'s toString())
My question is:
The MyString constructor function polluted the parent/global scope with a new method toString1() when called like this MyString('name'). I dont want this to happen. How do I create objects like the native?
You can check if your constructor is called with new very easily:
function MyString(val) {
if (this instanceof MyString) { // called with new
this.toString1 = function(){ return " " + val; }
this.name = 'My name is ' + val;
} else { // called without new
return '' + val;
}
}
Usually it's a good idea to set methods common to all your instances on the prototype, but i assume that was not the point of your question.
MyString.prototype.getMyName = function(){ return this.name; }
It looks like you should use prototype :
function MyString(val){
this.val = val;
}
MyString.prototype.toString1 = function(){ return " " + this.val }
var s = new MyString("thing");
console.log(s.toString1()); // logs " thing"
The toString1 isn't attached to the external scope. It's automatically accessible on all instances of MyString. The fact it's attached to the prototype and not to the object avoid the duplication of the function, making it more efficient.
If what you want is to avoid the MyString constructor to pollute the external scope when improperly called without the new operator, the answer, while it's easy, is Don't : Don't protect against flagrantly improper use of your API because it makes your code complex without gain. It's a lost fight anyway, bad coders will always find a way to fail using your code. Using new SomeClass(args) is basic JavaScript programming.
Try this:
MyString = function(name){ this.name = name; }
MyString.prototype.toString = function(){ return " " + this.name; }
Related
I'm asked to make a Javascript Module that acts as counter of browser events and is not possible to modify the actual counted events (Private method).
var CountingLogger = (function() {
var secret ={};
var uid = 0;
function CountingLogger(events) {
secret[this.id = uid++] = {};
// Store private stuff in the secret container
// instead of on `this`.
secret[this.id].events = events || 0;
}
CountingLogger.prototype.log = function (eventName) {
alert(secret[this.id].events[eventName]);
if (typeof secret[this.id].events[eventName] === 'undefined') {
secret[this.id].events[eventName] = 0;
}
secret[this.id].events[eventName]++;
var count = secret[this.id].events[eventName];
$('#logContents').append('<li>' + eventName + ': ' + count + '</li>');
};
return CountingLogger;
}());
in the main.js I define:
var logger = new CountingLogger();
then call
logger.log('EventName');
And should appear as callback a counter "EventName" + Counter, so Eventname: 1, SecondEvent: 4...
But in the log always shows 'WhateverEvent' undefined.
Can anybody please have an idea how this can be solved?
Regards
You don't want secrets at the level you have it. As Bergi said, it's a memory leak.
(Note: When I say "truly private" below, remember that nothing is truly private if someone's using a debugger. "Truly private" below just makes it's impossible for anyone to write code that, using a reference to the object, gets or modifies the private data.)
ES7 will have truly private properties. Until then, you basically have three options:
Truly private data, held via closures over the call to the constructor
"Keep your hands off" properties via a property naming convention
Very-hard-to-use properties that, while not private, are very hard to write code against
Truly Private Data
If you want truly private information on a per-instance basis, the standard way to do that is using variables in the constructor, and define methods that need that private data within the constructor:
function Foo() {
var secret = Math.floor(Math.random() * 100);
this.iWillTellYouASecret = function() {
console.log("The secret is " + secret);
};
}
Foo.prototype.iDoNotKnowTheSecret = function() {
console.log("I don't know the secret");
};
Yes, that means a new iWillTellYouASecret function is created for every instance, but it (and the secret) are also reclaimed when that instance is removed from memory, and a decent JavaScript engine can reuse the function's code across those function objects.
"Keep your hands off" Properties
But most of the time, you don't need truly private information, just information saying "keep your hands off me." The convention for that in JavaScript is properties beginning with an _. Yes, that means that code with access to instances can use or change that property's value, but that's actually true in most languages that have "truly private" properties as well, such as Java, via reflection.
Very-Hard-to-Use Properties
If you want to make life harder on people trying to use your private data, you can use this trick from an old blog article of mine *(it was written back when ES6 was going to have true privacy via Name objects; since then, Name has turned into Symbol and it isn't used for privacy anymore):
First, you create a Name psuedo-class:
var Name = function() {
var used = {};
function Name() {
var length, str;
do {
length = 5 + Math.floor(Math.random() * 10);
str = "_";
while (length--) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
}
while (used[str]);
used[str] = true;
return new String(str); // Since this is called via `new`, we have to return an object to override the default
}
return Name;
}();
Then you use this pattern for your private instance properties:
// Nearly-private properties
var Foo = (function() {
// Create a random string as our private property key
var nifty = new Name();
// Our constructor
function Foo() {
// We can just assign here as normal
this[nifty] = 42;
}
// ***On ES5, make the property non-enumerable
// (that's the default for properties created with
// Object.defineProperty)
if (Object.defineProperty) { // Only needed for ES3-compatibility
Object.defineProperty(Foo.prototype, nifty, {
writable: true
});
}
// ***End change
// Methods shared by all Foo instances
Foo.prototype.method1 = function() {
// This method has access to `nifty`, because it
// closes over the private key
console.log("Truly private nifty info: " + this[nifty]);
};
Foo.prototype.method2 = function() {
// Also has access, for the same reason
console.log("Truly private nifty info: " + this[nifty]);
};
return Foo;
})();
var f = new Foo();
f.method1(); // Can use nifty!
f.method2(); // Can too! :-)
// Both `method1` and `method2` are *reused* by all `Foo` objects
Now, the name of your private property is different every time your code runs.
This still isn't private. It's just harder to find.
Private methods in javascript should only be used for encapsulation purposes.
It's impossible to prevent someone from manipulating any method in javascript.
A user can simply place a debug point on your private method and start to manipulate your private logic.
I have a set of JavaScript "classes" where a base class defines functions that are then shared by an inherited class. It is working, and it is set up like this:
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
alert('Hi, ' + this.name + '!');
}
};
var ThingB = function() {
ThingA.call(this, 'Charlie');
};
ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;
var instanceOfB = new ThingB();
instanceOfB.sayHi(); // alerts 'Hi, Charlie!'
For reasons that are outside of my control, my company prefers to follow this pattern when writing JavaScript:
SomeClass = function() {
// "Private" functions go here
function somePrivateMethod() {
...
}
return {
// "Public" methods go here
somePublicMethod: function() { ... }
};
}();
Now, this is fine as far as things go, and it works well for many situations. But it is more of a functional style. There is only one "class" instance, and everything is static.
I've been asked to modify my working code to more closely match the style my company prefers. So my question is, there a way to inherit from a class that is wrapped inside a factory class? It would look something like this:
FactoryClassA = function() {
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
alert('Hi, ' + this.name + '!');
}
};
return {
createThingA: function(name) {
return new ThingA(name);
}
};
}();
FactoryClassB = function() {
// Define a ThingB class that inherits from ThingA somehow
return {
createThingB: function() {
return new ThingB();
}
};
}();
var instanceOfB = FactoryClassB.createThingB();
instanceOfB.sayHi(); // should alert 'Hi, Charlie!'
Is there a way to define ThingB wrapped in FactoryClassB that inherits from ThingA wrapped in FactoryClassA? Thanks to this question, I know that I'm not going to be able to do it exactly like this. I am thinking of using a method to extend a given class ... somehow?
This answer seems close, but I'm having trouble figuring out the details of how to modify that example to fit with the specifics of my situation. I am willing to bend my company's usual pattern a little bit, but can I at least get closer to it?
UPDATE 1
In response to Adam's comment to just add a parameter to the factory class, here's where I'm stuck:
ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;
I can't figure out how to adapt these lines to make it work if I just pass in a parameter to the factory class method.
Below is what (I believe) you're looking for:
FactoryClassA = function() {
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
console.log('Hi, ' + this.name + '!');
}
};
// Add the constructor back to the prototype
// (see explanation below)
ThingA.prototype.constructor = ThingA;
return {
createThingA: function(name) {
return new ThingA(name);
}
};
}();
FactoryClassB = function() {
// Bootstrapping:
// Capture the instance, as we'll need it to set up the prototype
var baseInstance = new FactoryClassA.createThingA();
// Capture the constructor
var baseConstructor = baseInstance.constructor;
// Keep a reference to the base prototype
var baseProto = baseConstructor.prototype;
function ThingB(name) {
// Call base constructor, along with our args
baseConstructor.call(this, name);
};
ThingB.prototype = baseInstance;
ThingB.prototype.constructor = ThingB;
ThingB.prototype.sayHi = function() {
console.log('here I am');
// call the base class `sayHi`
baseProto.sayHi.call(this);
};
return {
createThingB: function(name) {
return new ThingB(name);
}
};
}();
// Testing
var foo = FactoryClassB.createThingB("Indeed");
foo.sayHi();
// Output:
// here I am
// hi indeed
Explanation:
in FactoryClassA, this line is necessary:
ThingA.prototype.constructor = ThingA;
Note that every prototype in JS is automatically created with a reference to its constructor. For example, when you do:
function T(){}
T.prototype already has a property called constructor which points back to T.
However, in your implementation of ThingA, you reset the entire prototype, by doing ThingA.prototype = { ... }. Therefore, you now have lost the reference to its constructor. In 99% of cases it is ok, and won't have any negative side effects (which is probably why most developers tend to forget it). However, in the case of inheritance, it may be necessary.
Now, within FactoryClassB, we need to do some bootstrapping:
var baseInstance = new FactoryClassA.createThingA();
var baseConstructor = baseInstance.constructor;
var baseProto = baseConstructor.prototype;
Observe the last two lines, as they are pivotal to achieving inheritance in this design pattern. First, since ThingA's constructor is accessible via the prototype (ThingA.prototype.constructor = ThingA), then it means that given an instance of ThingA, we can directly retrieve its constructor. Since the constructor is the function itself, and since every function has a reference to its prototype, we can keep a reference of ThingA.prototype with baseConstructor.prototype.
Next is the critical part, where we set up the inheritance chain:
function ThingB(name) {
// Call the base constructor
baseConstructor.call(this, name);
};
ThingB.prototype = baseInstance;
ThingB.prototype.constructor = ThingB;
The last line above is quite important, as it tells the prototype what its constructor is, otherwise it would still point to ThingA.
There you have it - prototypal inheritance.
Side note:
You can probably see how the above can get quite tedious, a little grotesque, and repetitive. Ergo, you might want to consider an inheritance library like Fiber.js which follows the encapsulation pattern you desired (along with some bonuses like mixins and decorators). Disclaimer: I authored the library.
I found different ways that seem to work.
Mostly recommended way in textbooks and the internet:
var Person = function() {
this.age = 23;
}
Tony = new Person();
This also seems to work:
function Person() {
this.age = 23;
}
Tony = new Person();
Is there a difference? And an additional question: Usually you cannot simply leave out parentheses. Here it is possible (new Person instead of new Person()). This is because of using the new keyword, right?
A third odd way that I just tried out looks like this:
function Person() {
return {age: 2};
}
Tony = new Person();
Tony = Person(); // both ways work! It seems that you can leave out 'new' here.
Here I don't get an object with the name of my class, but my property is also accessible and it seems like it was quite similar to both above approaches.
What shall I use and what are the technical differences? Thank you!
JavaScript is a classless language. Classes don't exist, but objects may inherit properties from each other by using prototypes. This means you are not limited to implementing inheritance in a class-like manner. Personally, I like to use a BackboneJS-inspired method (code requires UnderscoreJS):
var BaseObject = function(){}; //Create a function so that we may use the new operator.
//There may be code in the constructor
BaseObject.extend = function(obj) { //Add a static function to the BaseObject to extend it
var base = this; //Save a reference for later
//Create the constructor for the sub object. We need to extend it, so we can't use the base constructor. AFAIK, this is the only way to clone the base constructor, i.e. by creating a new function that calls it
var SubObject = _.extend(function(){
base.apply(this, arguments); //Call base constructor
}, this);
SubObject.prototype= _.extend({}, this.prototype, obj); //Create new prototype that extends the super prototype, but does not overwrite it.
return SubObject; //Return the new constructor + prototype
};
This allows you to do cool class-like stuff like this:
var Car = BaseObject.extend({
speed: 0,
acceleration: 5,
accelerate: function(){
this.speed += this.acceleration;
}
});
var RaceCar = Car.extend({
acceleration: 10,
});
var car = new Car();
var raceCar = new RaceCar();
car.accelerate();
raceCar.accelerate();
if(raceCar.speed > car.speed){
console.log('raceCar won');
}else{
console.log('car won');
}
For more information on inheritance in JavaScript, I strongly recommend reading JavaScript: The Good Parts by Douglas Crockford.
Regarding your examples:
The difference between 1 and 2 is minimal. For more information see this question.
In 3, you are just returning an object literal. The new keyword only has influence on the this keyword within the function, which you are not using, and so using new has no effect. For more information, see this quesion
1 and 2 (var x = function vs function x) are very similar. 3 is a completely different thing.
The difference between 1 and 2 has nothing to do with classes and has been asked before on SO (several times). I think the most complete answer is this one:
https://stackoverflow.com/a/338053/1669279
In short, the first x points to an anonymous function and some debugging tools might have problems with that. The first one is available from the line it was defined on while the second is available in the entire scope. Read the linked answer for details.
The 3rd "solution" is not a class at all. It is simply a function that returns an object (might be called a Factory method).
It is not a good idea to return things from your constructors, especially return this. You should only return things if you want to override the normal process of creating objects (like implementing the singleton pattern for example).
As a side-note, you should always use new when you instantiate a class. Here is what happens when you try to be smart and save characters:
function X () {
return this;
}
console.log(X()); // outputs the window object
The parenthesis after calling the constructor with no parameters are optional, but it is frowned upon to avoid them because it results in slightly more confusing code.
To sum it up, i usually use pattern 1. Pattern 2 is also ok.
One problem with pattern 2 can be this one:
var x = new X(); // works
console.log(x.message); // works, I am X
x.method(); // doesn't work, method hasn't been defined yet
function X() {
this.message = 'I am X';
}
X.prototype.method = function() {
console.log(this.message);
};
this is how i do mine:
;(function (window) {
"use strict";
//-- Private Vars
var opt, obj, rm, Debug;
//-- construtor
function App(requestedMethod) {
//-- set up some vars
if(typeof requestedMethod !== 'undefined') {
rm = requestedMethod;
}
opt = {
rMethod: (typeof rm !== 'undefined') ? (rm != null) ? rm : false : false
}
//-- containe resulable objects
obj = {}
//-- call the init method
this.init();
}
/** Public Methods **/
/**
* The Init method called on every page load
*/
App.prototype.init = function () {
var om = opt.rMethod;
//-- Once all init settings are performed call the requested method if required
if(om) {(typeof App.prototype[om] == 'function') ? App.prototype[om]() : _DB('Call to Method [' + om + '] does not exsist.');}
};
/**
* testmethod
*/
App.prototype.testmethod = function () {
};
/** Private Methods **/
function PrivateMethod(){
}
/**
* A console output that should enable to remain enable js to work in IE
* just incase i forget to remove it when checking on those pesky IE browsers....
*/
function _DB(msg){
if(window.console && window.console.log){
var logDate = new Date();
window.console.log('------------------- ' + logDate + ' ----------------------------------');
window.console.log(msg);
}
};
window.App = App;
})(window);
then call it like:
<script src="ptha/to/your/app.js"></script>
<script>$(function() { new App('testmethod'); });</script>
When the code is loaded the new App() will then run once all page load data has completed
Hope this helps.To get access to it outside add the new to a var
var App = new App('testmethod);
then you can access things like
App.testmethod()...
var Person = function() {
this.age = 23;
}
Person is a variable that contains(is referenced) an anonymous function
function Person() {
this.age = 23;
}
but here you declare a function called "Person"
function Person() {
return {age: 2};
}
and so you declare a function that returns a new static object.
The best way depends on the needs, if you want to declare classes use the second, while to create the modules uses the third. For the first method look here: http://helephant.com/2008/08/23/javascript-anonymous-functions/
I've been reading the chapter on functional inheritance in Crockford's 'The Good Parts'. In the mammal example he gives I'm a bit confused as to why he uses the superior method to modify the get_name function. Here is the example in question:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
var mammal = function (spec) {
var that = {};
that.get_name = function () {
return spec.name;
};
that.says = function () {
return spec.saying || '';
};
return that;
};
var myMammal = mammal({
name: 'Herb'
});
var cat = function (spec) {
spec.saying = spec.saying || 'meow';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
that.get_name = function () {
return that.says() + ' ' + spec.name + ' ' + that.says();
};
return that;
};
Object.method('superior', function (name) {
var that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});
var coolcat = function (spec) {
var that = cat(spec);
var super_get_name = that.superior('get_name');
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
var myCoolCat = coolcat({
name: 'Bix'
});
var name = myCoolCat.get_name(); // 'like meow Bix meow baby'
I'm confused about this because I can replicate the same thing by removing the superior method and just changing coolcat as follows:
var coolcat = function(spec) {
var that = cat(spec);
var super_get_name = that.get_name();
that.get_name = function(n) {
return 'like ' + super_get_name + ' baby';
};
return that;
};
So, I don't understand why Crockford chooses to use the superior method. Is anyone able to explain at all?
The idea here is that this:
var super_get_name = that.superior('get_name');
makes super_get_name into a function that — every time it is called — invokes that's original get_name method. This allows the new get_name to call the old (super-class) get_name.
Now, if the original get_name method will never have any effect other than to return a single value that never changes, then yeah, this is kind of pointless; you can just save that single-value-that-never-changes and then use it in the new get_name. But if the original get_name can actually do things (such as, say, run an AJAX request, or change the styling of an HTML element), or if its return-value can change (say, if there were some corresponding set_name method), then there would be an important difference between what your code does (save the original return-value and use it) and what Crockford's code does (save the original method and invoke it).
The confusion that arises from this chapter of Crockford's book arises as what Crockford describes is "his" preferred pattern for implementing inheritance in JavaScript, which relies on his extending the Function object with the Function.prototype.method (chapter 1.3) which he uses to add methods to the Function object.
The problem addressed in the coolcat example is the need to access the method of the parent type. In 'classical' OO languages like Java this is natural as classes exist in their own right. In JavaScript inheritance is prototypical, you make an object of type mammal and then modify the object to create the type cat or coolcat.
Depending on your design you may add properties and functions or override an 'inherited' function. The problem arises when you override an 'inherited' function, in JavaScript you basically replace the old function with the new function, thereby loosing the older function.
Crockford now needs to do two things:
get the parent's (cat's) get_name method; and
save it in a manner that can be used from within the overridden method.
In this code:
var coolcat = function(spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function(n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
He does 1. by calling the superior method to get a function that gets the cat's get_name function;
and he does 2. by saving it to the super_get_name variable within the coolcat function(/object) allowing access to the cat's get_name function before it is overridden (more correctly overwritten) by the coolcat's get_name function.
In my opinion the confusion arises because:
The superior method is named oddly: the 'superior' method is simply a function look up by name method and could be better named, for example as getFunctionByName (you can try this by replacing the string get_name, by purr, the coolcat's get_name will now call purr, just remember to call it as super_get_name(10) otherwise you'll get an empty string back).
Secondly the code and the pattern obfuscates the code by relying on some particular Crockford patterns, and is likely to stresses you out if you attempt to dive into this chapter without having followed the entire book.
I think there is a simpler way to achieve this, one that I think because it is completely localized is easier to understand etc., as in the code below:
var coolcat = function(spec) {
var that = cat(spec);
that.parent_get_name = that.get_name;
that.get_name = function() {
return 'like ' + this.parent_get_name() + ' baby';
};
return that;
};
There are some other oddities for example the argument n in definition of the coolcat get_name function, which I can only assume came from copying the purr function, which would suggest a ghost writer!
Finally, I would suggest that before one reads the book one should listen to his talk on 'JavaScript the good parts'. The talk is absolutely brilliant, much better than the book.
I am working on a parser combinator library in JavaScript. For that I want to create functions that can be called like any other functions, but also have member functions that can be called in turn to produce output based on the function they are attached to (e.g. combinators).
I can of course add members to functions like this:
//the functions I want to add additional members to
function hello(x) {
return "Hello " + x;
}
function goodbye(x) {
return "Goodbye " + x;
}
//The function I want as a member of the above functions.
//it creates another function based on the function it is
//attached to.
function double() {
var that = this;
return function(x) {
return that(x) + ", " + that(x);
};
}
//I can attach them manually to the function objects:
hello.double = double;
//calling hello.double()('Joe') results in => "Hello Joe, Hello Joe"
goodbye.double = double;
//calling goodbye.double()('Joe') results in => "Goodbye Joe, Goodbye Joe"
I could create a function that augments all my functions with a double member, but I would have to remember to call it every time I create a Hey, Sayonara, etc. function. Also my greeting functions would have all those members each, directly on the function object, for each instance. I would prefer to put them all in one prototype and make this the prototype of all my greeting functions. The following options don't work either:
replacing hello.__proto__ (nonstandard, won't work in all browsers)
modifiying Function.prototype directly (would add those members to all other functions as well, but they do not make sense there - I only want to call double on a set of my own functions)
Is it even possible to give a function object a custom prototype or am I stuck with modifying each function object I create?
Update: I changed the above example to be more similar to the actual problem I am working on. This is about modyfing function objects not normal objects. The final goal is to enable a comfortable syntax for parser combinators, e.g. (much simplified):
//parses one argument
var arg = …
//parses one function name
var name = …
//parses a function call, e.g. foo(x+y, "test", a*2)
var functionCall = name.then(elem("(")).then(arg.repSep(",")).then(")").into(process(…))
I want to be able to add members to a set of functions so, when these members are called, they return new functions based on the function on which they were called. This is to be used for parser combinators / monadic parsers.
Yes, you can, using setPrototypeOf.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf.
function prototype() { }
prototype.double = function() { console.log("double"); };
function myfunc() { }
Object.setPrototypeOf(myfunc, prototype);
myfunc.double();
This is essentially the standardized version of __proto__.
There is no other way to directly create a function with a prototype other than Function.prototype. Consider:
function makeFunc() {
return function x() { };
}
function protofunc { }
protofunc.double = { }...
makeFunc.prototype = protofunc;
new makeFunc()
Unfortunately, by returning a function from the makeFunc constructor, rather than the default this, the makeFunc.prototype is not applied.
Or:
myFunc = Object.create(protofunc, ???);
Normally we think of using Object.create to create an object with a prototype, but in this case, there's no way to specify a function as being the object.
Bottom line: the only alternative is to set the prototype explicitly, which you can do either with __proto__, or setPrototypeOf. This is an ES6 feature. Normal browser support caveats apply. See http://kangax.github.io/compat-table/es6/.
Although I know you asked for a solution without using Function.prototype, I wonder whether you had considered that you can chain conditionally-executing behaviors such that a Function.prototype function like double() will allow a co-existence of different behaviors depending on "class" instance...
// This could also be adapted to itself be on Function.prototype
function chainConditions () {
var args = arguments;
return function () {
for (var i=0, argl = args.length; i < argl; i++) {
var ret = args[i].apply(this, arguments);
if (typeof (ret) !== 'undefined') { // If you want to allow undefined to be returnable, you could instead add this to a try-catch and ignore those which throw exceptions or a certain exception
return ret;
}
}
};
}
Function.prototype.double = function () {
if (this.prototype instanceof Salutation) {
var that = this;
return function(x) {
return that(x) + ", " + that(x);
};
}
};
Function.prototype.double = chainConditions(
function () {
if (this.prototype instanceof Tennis) {
var that = this;
return function(x) {
return that(x) + ", " + that(x);
};
}
},
Function.prototype.double
);
function Salutation () {}
function Hello(x) {
return "Hello " + x;
}
function Goodbye(x) {
return "Goodbye " + x;
}
Goodbye.prototype = new Salutation();
function Tennis () {
}
function TennisPlayer (x) {
return x + ' serve';
}
TennisPlayer.prototype = new Tennis();
alert(TennisPlayer.double()('Forehand')); // Forehand serve, Forehand serve
alert(Goodbye.double()('Yellow Brick Road')); // Goodbye Yellow Brick Road, Goodbye Yellow Brick Road
alert(Hello.double()('Yellow Brick Road')); // does not work as we did not use Hello.prototype = new Salutation();
One should be able to abstract this even further by allowing one function to be used for the class type checking (e.g., grouping all Salutation methods on the Function.prototype together as one type check), and another to accept a list of methods keyed to their conditional behaviors.
While it uses its own API, it is fairly non-obtrusive and can even be made to work with existing methods on the Function.prototype which do not play along by throwing an exception (just be sure to include any pre-existing methods last).
A couple of different options. I think you should be thinking in terms of objects and inheritance instead of functions and globals. In the example above, you are basically implying you want "world" to inherit the set of hello methods. (Or do you want "hello" to inherit "world"?)
You should start by reading this paper here: http://www.crockford.com/javascript/inheritance.html
Here's some simple code that demonstrates inheritance using "prototypal inheritance"
// ---------------
function inherit (obj, base) {
var tmp = function () { };
tmp.prototype = base.prototype;
obj.prototype = new tmp();
obj.prototype.constructor = obj;
};
function HelloSet() {
;
}
HelloSet.prototype.helloA = function() {
return "Hello A " + this.displayName;
};
HelloSet.prototype.helloB = function() {
return "Hello B " + this.displayName;
};
function World(displayName) {
HelloSet.constructor.call(this); // constructor chaining
this.displayName = displayName;
}
inherit(World, HelloSet); // World now has all the methdods of HelloSet
// ---------------
// now let's create some worlds
var earth = new World("Earth");
var mars = new World("Mars");
earth.helloA(); // returns "Hello A Earth"
mars.helloB(); // returns "Hello B Mars"
A short answer to your question would be: Yes.
function Parent() {
// constructor
}
function Child() {
// constructor
}
Child.prototype = new Parent();
Here's how to add methods to your Child class:
Child.prototype.someMethod = function() {
// do something
}
It's been a long time that I've used Javascript in an object-oriented fashion unfortunately, but I believe there are some solutions to make the syntax a little bit clearer.