So I know javascript pretty well, but I'm not sure about this one.
Tough to explain so I'll just show it:
var view = new View();
view.rating = 4.5;
Is there anyway to have view.rating be called as a function to manipulate the DOM a bit and set that rating to five?
So in View:
View.prototype = {
rating : function() {
$('div.stars').width(4.5);
}
}
I know there are workarounds, using something other than "view.rating = 5". I'm not interested in those. I'm wondering if there is a way to set this up maintaining view.rating = 5. This is coming JS is coming straight from PHP essentially and I don't want to bog the PHP down with anonymous functions.. like view.rating = function() {...};
Thanks!
Matt Mueller
No. (Edit: not on all implementations of common browsers at least)
There isn't anything in Javascript equivalent to "overloading the = operator".
Edit:
I'm not sure if this is clear to you. If you make rating a function (either via the prototype or not), you should call it like view.rating(5), and it can update the DOM (or do anything).
Most implementations of JavaScript don't support creating getter/setter properties so it wouldn't be super useful on the web. However there are some implementations that do. Here's an example in Mozilla's implementation:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Getters_and_Setters
EDIT: Let me just clarify, writing getters/setters is syntactic sugar over the use of a getFoo()/setFoo(foo) style property. It is for the developer's benefit. IMO, for a web app (due primarily to IE's lack of support) it isn't quite realistic just yet. While IE market share is dropping, depending upon your demographics in a widely public app, a lot of your visitors at this point still won't have support for them.
Some more links of interest for you:
http://www.robertnyman.com/javascript/#javascript-getters-setters-object-defineproperty-compatibility
http://ejohn.org/blog/javascript-getters-and-setters/
http://blogs.msdn.com/ie/archive/2009/01/13/responding-to-change-updated-getter-setter-syntax-in-ie8-rc-1.aspx
Related
If I implemented a method x on a String like :
String.prototype.x = function (a) {...}
And then the new version of javascript actually implements the x method, but on the another way, either returning something different than my implementation or function with more/less arguments than my implementation. Will this break my implementation and override it?
You'll overwrite the default implementation.
Any code that uses it will use yours instead.
There was a proposal for scoped extension methods and it was rejected because it was too expensive computationally to implement in JS engines. There is talk about a new proposal (protocols) to address the issue. ES6 symbols will also give you a way around that (but with ugly syntax).
However, that's not the punch - here's a fun fact no one is going to tell you.
No one is ever going to implement a method called x on String.prototype
You can implement it and get away with it. Seriously, prollyfilling and polyfilling is a viable, expressive and interesting solution to many use cases. If you're not writing a library I think it's acceptable.
No, you'll be overriding the default implementation of said function, from the point at which you've declared/defined it. The "new" implementation will function in its native behavior, until your implementation's defined.
var foo = 'some arbitrary string';
console.log(foo.indexOf('s')); // logs [0]
String.prototype.indexOf = function(foo, bar) { return 'foo'; };
console.log(foo.indexOf()); // logs [foo]
Illustration: http://jsfiddle.net/Z4Fq9/
Your code will be overriding the default implementation.
However if the interface of your method is not compatible with the standard one the libraries you may use could depend on the standard behavior so the program as a whole could break anyway with newer versions of the libraries.
In general is a bad idea doing something that could break if others do the same: what if another library thinks it's a good idea to add a method x to the standard string object prototype? Trying to avoid conflicts is a must for libraries but it's also good for applications (and if an application is written nicely then a lot of its code is probably quite similar to a library, and may evolve in a library later).
This kind of "patching" makes sense only to provide the a standard method for broken or old javascript implementations where that method is absent. Patching standard prototypes just because you can is a bad idea and will make your code a bad neighbor with which is difficult to share a page.
If the implementation of x is from a new version of Javascript, it's part of the core, therefore when you write String.prototype.x... it will be already there, and you will overwrite it.
Best practice in this kind of things is to write
if( !String.prototype.x ){
String.prototype.x = function ...
//your
We have been debating how best to handle objects in our JS app, studying Stoyan Stefanov's book, reading endless SO posts on 'new', 'this', 'prototype', closures etc. (The fact that there are so many, and they have so many competing theories, suggests there is no completely obvious answer).
So let's assume the we don't care about private data. We are content to trust users and developers not to mess around in objects outside the ways we define.
Given this, what (other than it seeming to defy decades of OO style and history) would be wrong with this technique?
// namespace to isolate all PERSON's logic
var PERSON = {};
// return an object which should only ever contain data.
// The Catch: it's 100% public
PERSON.constructor = function (name) {
return {
name: name
}
}
// methods that operate on a Person
// the thing we're operating on gets passed in
PERSON.sayHello = function (person) {
alert (person.name);
}
var p = PERSON.constructor ("Fred");
var q = PERSON.constructor ("Me");
// normally this coded like 'p.sayHello()'
PERSON.sayHello(p);
PERSON.sayHello(q);
Obviously:
There would be nothing to stop someone from mutating 'p' in unholy
ways, or simply the logic of PERSON ending up spread all over the place. (That is true with the canonical 'new' technique as well).
It would be a minor hassle to pass 'p' in to every function that you
wanted to use it.
This is a weird approach.
But are those good enough reasons to dismiss it? On the positive side:
It is efficient, as (arguably) opposed to closures with repetitive function declaration.
It seems very simple and understandable, as opposed to fiddling with
'this' everywhere.
The key point is the foregoing of privacy. I know I will get slammed for this, but, looking for any feedback. Cheers.
There's nothing inherently wrong with it. But it does forgo many advantages inherent in using Javascript's prototype system.
Your object does not know anything about itself other than that it is an object literal. So instanceof will not help you to identify its origin. You'll be stuck using only duck typing.
Your methods are essentially namespaced static functions, where you have to repeat yourself by passing in the object as the first argument. By having a prototyped object, you can take advantage of dynamic dispatch, so that p.sayHello() can do different things for PERSON or ANIMAL depending on the type Javascript knows about. This is a form of polymorphism. Your approach requires you to name (and possibly make a mistake about) the type each time you call a method.
You don't actually need a constructor function, since functions are already objects. Your PERSON variable may as well be the constructor function.
What you've done here is create a module pattern (like a namespace).
Here is another pattern that keeps what you have but supplies the above advantages:
function Person(name)
{
var p = Object.create(Person.prototype);
p.name = name; // or other means of initialization, use of overloaded arguments, etc.
return p;
}
Person.prototype.sayHello = function () { alert (this.name); }
var p = Person("Fred"); // you can omit "new"
var q = Person("Me");
p.sayHello();
q.sayHello();
console.log(p instanceof Person); // true
var people = ["Bob", "Will", "Mary", "Alandra"].map(Person);
// people contains array of Person objects
Yeah, I'm not really understanding why you're trying to dodge the constructor approach or why they even felt a need to layer syntactical sugar over function constructors (Object.create and soon classes) when constructors by themselves are an elegant, flexible, and perfectly reasonable approach to OOP no matter how many lame reasons are given by people like Crockford for not liking them (because people forget to use the new keyword - seriously?). JS is heavily function-driven and its OOP mechanics are no different. It's better to embrace this than hide from it, IMO.
First of all, your points listed under "Obviously"
Hardly even worth mentioning in JavaScript. High degrees of mutability is by-design. We're not afraid of ourselves or other developers in JavaScript. The private vs. public paradigm isn't useful because it protects us from stupidity but rather because it makes it easier to understand the intention behind the other dev's code.
The effort in invoking isn't the problem. The hassle comes later when it's unclear why you've done what you've done there. I don't really see what you're trying to achieve that the core language approaches don't do better for you.
This is JavaScript. It's been weird to all but JS devs for years now. Don't sweat that if you find a better way to do something that works better at solving a problem in a given domain than a more typical solution might. Just make sure you understand the point of the more typical approach before trying to replace it as so many have when coming to JS from other language paradigms. It's easy to do trivial stuff with JS but once you're at the point where you want to get more OOP-driven learn everything you can about how the core language stuff works so you can apply a bit more skepticism to popular opinions out there spread by people who make a side-living making JavaScript out to be scarier and more riddled with deadly booby traps than it really is.
Now your points under "positive side,"
First of all, repetitive function definition was really only something to worry about in heavy looping scenario. If you were regularly producing objects in large enough quantity fast enough for the non-prototyped public method definitions to be a perf problem, you'd probably be running into memory usage issues with non-trivial objects in short order regardless. I speak in the past tense, however, because it's no longer really a relevant issue either way. In modern browsers, functions defined inside other functions are actually typically performance enhancing due to the way modern JIT compilers work. Regardless of what browsers you support, a few funcs defined per object is a non-issue unless you're expecting tens of thousands of objects.
On the question of simple and understandable, it's not to me because I don't see what win you've garnered here. Now instead of having one object to use, I have to use both the object and it's pseudo-constructor together which if I weren't looking at the definition would imply to me the function that you use with a 'new' keyword to build objects. If I were new to your codebase I'd be wasting a lot of time trying to figure out why you did it this way to avoid breaking some other concern I didn't understand.
My questions would be:
Why not just add all the methods in the object literal in the constructor in the first place? There's no performance issue there and there never really has been so the only other possible win is that you want to be able to add new methods to person after you've created new objects with it, but that's what we use prototype for on proper constructors (prototype methods btw are great for memory in older browsers because they are only defined once).
And if you have to keep passing the object in for the methods to know what the properties are, why do you even want objects? Why not just functions that expect simple data structure-type objects with certain properties? It's not really OOP anymore.
But my main point of criticism
You're missing the main point of OOP which is something JavaScript does a better job of not hiding from people than most languages. Consider the following:
function Person(name){
//var name = name; //<--this might be more clear but it would be redundant
this.identifySelf = function(){ alert(name); }
}
var bob = new Person();
bob.identifySelf();
Now, change the name bob identifies with, without overwriting the object or the method, which are both things you'd only do if it were clear you didn't want to work with the object as originally designed and constructed. You of course can't. That makes it crystal clear to anybody who sees this definition that the name is effectively a constant in this case. In a more complex constructor it would establish that the only thing allowed to alter or modify name is the instance itself unless the user added a non-validating setter method which would be silly because that would basically (looking at you Java Enterprise Beans) MURDER THE CENTRAL PURPOSE OF OOP.
Clear Division of Responsibility is the Key
Forget the key words they put in every book for a second and think about what the whole point is. Before OOP, everything was just a pile of functions and data structures all those functions acted on. With OOP you mostly have a set of methods bundled with a set of data that only the object itself actually ever changes.
So let's say something's gone wrong with output:
In our strictly procedural pile of functions there's no real limit to the number of hands that could have messed up that data. We might have good error-handling but one function could branch in such a way that the original culprit is hard to track down.
In a proper OOP design where data is typically behind an object gatekeeper I know that only one object can actually make the changes responsible.
Objects exposing all of their data most of the time is really only marginally better than the old procedural approach. All that really does is give you a name to categorize loosely related methods with.
Much Ado About 'this'
I've never understood the undue attention assigned to the 'this' keyword being messy and confusing. It's really not that big of a deal. 'this' identifies the instance you're working with. That's it. If the method isn't called as a property it's not going to know what instance to look for so it defaults to the global object. That was dumb (undefined would have been better), but it not working properly in that scenario should be expected in a language where functions are also portable like data and can be attached to other objects very easily. Use 'this' in a function when:
It's defined and called as a property of an instance.
It's passed as an event handler (which will call it as a member of the thing being listened to).
You're using call or apply methods to call it as a property of some other object temporarily without assigning it as such.
But remember, it's the calling that really matters. Assigning a public method to some var and calling from that var will do the global thing or throw an error in strict mode. Without being referenced as object properties, functions only really care about the scope they were defined in (their closures) and what args you pass them.
I am not trying to ask another JQuery vs. Prototype vs... topic as I have already read 5+ of those on these forums and have been able to gain a lot of knowledge from them. My question is more directly related to wanting the ability to use inheritance for basic classes and not actually sure what would be a good choice.
To be brief, I have the requirement to be able to control theoretical objects in javascript and manipulate them based on user input then display them.
I have used JQuery and enjoy how easy it is to modify the DOM (which appears to be it's main goal). However from all the readings I have done, it seems that JQuery has no intention of assisting you in dealing with classes, inheritance etc. If I have already chosen JQuery to display and manipulate the data what would be a good choice to assist me with the inheritance issue.
My first thought was Mootools or Prototype, however prototype DOM Extension seems to be a very bad approach and would rather wait for Prototype 2.0 unless this isn't an issue on commonly supported browsers now.
I had also read about Base2, Joose, and JS.Class, but don't know if they will do what I am hoping for either.
Any suggestions based on the above information would be great, again, I am not trying to figure out the pro's and con's of the commonly used JS frameworks.
Why emulate classical inheritance?
What's wrong with functions and .prototype?
var SomeObject = function(data) {
this.data = data;
}
SomeObject.prototype.doStuff = function() {
return this.data;
}
Do it the old fashioned way.
If you want to use anything besides jQuery I would recommend underscore for it's syntactic sugar.
If you must emulate classical OO, I would recommend oorja as it's the lesser of evils.
Would you consider extending the native elements via the prototype dangerous? I see some frameworks such as Prototype doing this so I have started to wonder if I dare to do that too.
I am worried about implementing things like addClassName and make it collide in the future in a way that I can't resolve any other way than rewriting the software and asking module authors to do the same.
I wouldn't because IMHO it might definitely make collisions soon or later and create a potential bug very difficult to be spot out.
I anyway do extend some basic simple native Javascript objects like String.trim, I'm anyway careful to always test to see if it already exists by using a simple if test:
if(!String.prototype.trim)
String.prototype.trim = function() { return this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }
You could do the same with addClassName.
The difference is that doing it with simple function like String.trim, it's difficult that might lead to problems in future, because even if a browser engine has got String.trim (actually FF has it) well such a function is going exactly to do what my String.trim does, so you won't see differences in your web application workflow ever.
A more complex function like overriding querySelectorAll might lead to differences between how the browser implements it and your implementation. For example: the order of the returned elements might be different, the browser function returns a collection while your one an array, and other issues. So when you run your webapp on browser that does implement the querySelectorAll it might lead to having your webapp not working anymore as expected, and there try finding out the bug!!!
Maybe querySelectorAll is not the best example, but I hope I explained the concept.
I'm working on a site and using JQuery for essentially the first time. I've mostly used MooTools for previous projects, and I have a few widget classes I've written using the MooTools Class structure. I'd like to port them over to JQuery, but it looks to me like there is nothing similar to the MooTools functionality when it comes to object classes.
I've searched around a bit, and haven't found much on it. Digg appears to have rolled their own, but I'm not sure if this is something I should be using. Is there a better way? How object-oriented do people normally get with JQuery? What's the usual method of encapsulating a UI widget (or any functional class structure)?
I'll post a fake example of a possible MooTools widget class:
var ZombatWidget = new Class({
Extends: BaseWidget,
widgetPropertyX = 'prop1',
widgetPropertyY = 'prop2',
attach = function(el) {
var f = function() {
//do something widgety
};
el.addEvent('dblclick',f);
el.addClass('widgetized');
}
});
var z = new ZombatWidget();
z.attach($('widgetDiv'));
What I've got is a lot bigger than that, but you get the idea. Do I need to convert this to the prototype method of class/inheritance structuring? How would you write this kind of object class using JQuery?
You might find this approach useful to the task at stake: building an object-oriented jquery plugin.
And this article on Ajaxian "a real OO class system with jquery".
Hm... interesting. We have jQuery which imho is a great tool to interact with the DOM. It's a selection tool where you can write your own code (plugins) to modify selected items. You can interact here with your own (object oriented) code in a plugin to do something really cool.
So why would you need extra OO capabilities in jQuery unless you want to be able to inherit from other jQuery plugins?
Because you might have a plugin that allows you to do the following:
$(".spiffyness").yourSpiffyficationPlugin1();
And, while doing some really cool awesomeness already, you need more spiffyness on top of this.
Therefore you want to inherit from your first plugin which results in:
$(".spiffyness").yourSpiffyficationPlugin2(); //plugin inherited from 1
But... wouldn't you get there too by doing this:
$(".spiffyness").yourSpiffyficationPlugin1().yourSpiffyficationPlugin2();
Where the second plugin just does this tiny (but awesome ;)) thing extra on top of the first one?
In other words: is what you want, worth the effort for the sake of OO purism? Or is the jQuery pipe mechanism good enough and maybe everything you need?
I would say that separation of responsibilities and/or your mootools mindset might be the real issue here. Let jQuery do what it is good at, use it's powerfull pipe mechanism, pipe your own plugins (which may contain tons of fancy OO stuff)... and you can have great results while your code is still clean.
If you do think I am thinking too simple here, a good example of the essence of your point would be welcome! :-)
And to be ahead of that, if you are doing something really advanced and you do not get away with simply doing something on top of something else, you're plugin could also delegate to one of your OO classes. E.g. like:
$.fn.totalAwesomeness = function(options) {
var defaults = {
mode: 1,
title: 'Awesome'
};
var opts = $.extend(defaults, options);
return this.each(function() {
var $this = $(this);
var handler = null;
if(defaults.mode == 1)
handler = new com.myStuff.class1($this);
else if(defaults.mode == 2)
handler = new com.myStuff.class2($this); //class2 inherits from class1
handler.doMagic();
});
};
You can always also use moo4q - http://moo4q.com/ . It adds MooTools class support to jQuery.
I wrote an article some time ago about jQuery object oriented plugins, hope it will be helpful
http://ajax911.com/jquery-object-oriented-plugins/
There are third party javascript class implementations that provide very powerful introspection capabilites. I would like to particularly highlight JS.Class and Joose.
While JS.Class is modeled after Ruby, Joose is modeled after Moose.
I am not a mootools user so I can not comment on their advantages/disadvantages with respect to mootools. But I would summarize their key features.
JS.Class has a strong focus on simulating the Object oriented features of Ruby and does a pretty good job at that. It provides a powerful library modeled after the standard library of Ruby and also comes with a well integrated package management and testing framework.
Joose, while provides no testing framework/package management facilites, excels in terms of
advanced attribute management facilities, filters and better introspection facilities.
Both of them have really good documentation and can be used in browser as well as server.
I've just finished a very first release of my mini project: https://github.com/op1ekun/plOOgins. It's all about writing OOP code to be used as Jquery plugins. It's not rocket science just a little something that we wanted to use at my workplace. Maybe it will help You a bit. Good luck!
Plugins sometimes do the trick.
Of course, you could use just enough of mootools to get it's class/inheritance model. With the implementation of document.id "compatibility mode" in 1.2.3 you can have your cake and eat it too (I think--haven't done it myself.)
The question is... Why are you moving away from MooTools is it fits your needs? Seems to me like MooTools was working fine, and there is nothing jQuery does that MooTools can't do. (The opposite isn't true).
Unfortunately, jQuery is not built to support classical OOP as MooTools is so you will need to write your Classes as jQuery plugins.