I have heard that ES6 now finally permits subclassing Array. Here's an example given by
class Stack extends Array {
constructor() { super() }
top() { return this[this.length - 1]; }
}
var s = new Stack();
s.push("world");
s.push("hello");
console.log(s.top()); // "hello"
console.log(s.length); // 2
Sure, that works. But in Traceur at least, setting the length explicitly does not truncate the array. And when printing via console.log, the output is in object form rather than array form, suggesting that somebody is not looking at it as a "real" array.
Is this a problem with how Traceur implements subclassing built-in objects, or a limitation of ES6?
Long answer
In the normal case, the subclassing in Ecmascript 6 is just syntactic sugaring, so it still does the prototypical chaining that Ecmascript 5 does. This means that extending types in Traceur is in most cases exactly the same as extending in "real" ecmascript 6.
Array instances are special – the ECMAScript 6 specification calls them exotic. Their handling of the property length can’t be replicated via normal JavaScript. If you invoke your constructor then an instance of Stack is created, not an exotic object (exotic is actually the official name in the ES6 spec).
But do not despair, the solution is not provided by the class extends sugaring itself, but by the (re)introduction of the __proto__ property.
The solution
Ecmascript 6 reintroduces the writable __proto__ property. It was once only available on Firefox and was deprecated, but is now back in full force in ES6. This means that you can create a real array and then "upgrade" it to your custom class.
So now you can do the following:
function Stack(len) {
var inst = new Array(len);
inst.__proto__ = Stack.prototype;
return inst;
}
Stack.prototype = Object.create(Array.prototype);
Short answer
So subclassing should work in ES6. You might have to use the __proto__ trick manually if they have not manage to sugar the process using the new class extends syntax with some yet undisclosed trickery. You will not be able to use the transpilers such as Traceur and Typescript to accomplish this in ES5, but you might be able to use the code above in ES5 using Firefox that (as far as I remember) have supported __proto__ for quite some time.
The problem is that you are overriding the constructor. If you remove your constructor () { super(); }, your example works perfectly, including s.length = 0 truncating the array.
Related
Rivets.js proposes to use the adapter.read and adapter.publish functions to get and set properties of a model while defining binders. I have not found an actual benefit of using read/publish when compared to the standard get/set methodology.
Excerpt from documentation:
adapter.read(model, keypath)
adapter.publish(model, keypath, value)
The source code for read and publish from v0.6.10
read: function(obj, keypath) {
return obj[keypath];
},
publish: function(obj, keypath, value) {
return obj[keypath] = value;
}
I wonder if anyone knows about the benefits that read and publish may offer?
I finally figured this out. The answer is as simple as abstracting the get and set functionalities from the binder. This has no real benefit if using rivets as is with the one and only dot (.) binder which it ships with. But this approach comes in very handy when one defines custom adapters.
A good example, like in my case, is when using the rivets-backbone adapter. The model passed to the binder could be a plain old java object or a backbone model. Reading and writing of properties on the object vary based on its type. By using the publish and read functions, this logic gets abstracted from the binders implementation.
I am trying to use Mootools together with TypeScript. Mootools, and some modern browsers support .bind method, which is polymorphic.
How can I properly declare this feature in a *.d.ts file, to be able to use constructs like [1,2].map(this.foo.bind(this)); ?
I know I can avoid such constructs by using lambdas, but sometimes I do not want to.
Perhaps there is a mootools.d.ts file somewhere which I could download instead of reinventing it myself?
TypeScript's lib.d.ts already defines the bind function's signature in the Function interface as follows:
bind(thisArg: any, ...argArray: any[]): Function;
I don't think there's any better way of doing it until generics get added to the language.
For the time being though, if you want to use bind and the recipient of the resulting function expects a specific signature, you're going to have to cast the function back to that signature:
var bfn : (p: number) => string;
bfn = <(p: number) => string> fn.bind(ctx);
There's a growing list of definition files being tracked here.
As for generating methods pre-bound to their this pointer in TypeScript I've suggested two ways of doing this. 1) a simple base class I defined at the end of this thread. and 2) a more advanced mixin & attribute system here.
Basically, I want to modify the constructor of the Object
class. Since every class extends Object, I hope whenever any
object of any class is instantiated, the modified function will
be called.
So I did this :
Object.prototype.constructor = function (){
trace("it was called;");
};
and put a breakpoint on the trace statement.
But it didn't stop there.
The trace statement did not get executed also.
Any solutions/suggestions?
In which context are you coding?
If you're using the Flex Compiler MXMLC (default, if you're in FlashBuilder), than you could add the compiler option -es. This should make AS3 feel more like AS2 and JS and support the prototype chain inheritance.
-compiler.es alias -es
"use the ECMAScript edition 3 prototype based object model to allow dynamic overriding of prototype properties. In the prototype based object model built-in functions are implemented as dynamic properties of prototype objects. (advanced)"
I don't know, if this plays well with all the extensions Adobe added to the ECMA Script standard, like packages, namespaces and classes. But you could give it a try.
I don't think it's possible in AS-3, but it was in AS-2.
Mootools classes have an initialize() method that's called when a new object is instantiated.
It seems that setup() is a commonly used method as well.
Most classes I've observed call this.setup() from initialize() and nowhere else, which has left me wondering:
What's the purpose of setup()? Why not just put the setup() code in initialize()? When does it make sense to use a setup() method?
as oskar says, there's no benefit to using that very name. If you wanted to, you could only use a single initialize function with a bunch of anonymous functions within and events but it does not make for very easy code to read, extend and maintain.
i tend to use methods like this.setupScene() and this.attachEvents() to abstract different actions. within these methods, i tend to loop through items and call smaller pseudo-private methods that do the singular dom manipulation required or element.addEvent, aka, this.elements.each(function(el) { this._attachEvent(el, "something"); }, this);
If you are sharing code with other users, there are certain conventions most mootools authors try to adhere to when releasing plugins or contributing to the core and more forks.
for example, if the class relates to an element or an array of elements, always set this.element = document.id(el); etc.
for reference on best practices: http://ryanflorence.com/11-tips-for-creating-great-mootools-plugins/
or even http://davidwalsh.name/mootools-class-tips
after a while, they start making perfect sense and will help you tremendously in your work.
There is no benefit whatsoever in using a setup/build/whatever function that is only called from the initialize function of a mootools Class.
I guess the distinction comes from languages where you don't have variable function arguments but rather overload function names with different sets of arguments. Like Java.
In Java this makes perfect sense. When you have multiple constructors that differ in the arguments they accept, then you handle the argument specific operations in your constructor and the common stuff, that every constructor needs to call in a method that is called by all constructors.
Personally I don't make this distinction in my mootools Classes, but rather only outsource functionality in its own function, if there is need to reuse the code from another function.
Don't get confused by setup functions, there is no hidden power to them.
setup is not a private MooTools method. It's not going to do anything until you create an actual method named this way.
There's one instance of this method in MooTools-more, and it's nothing beyond a simple keyword, just like createDefaults() or setInitialStuff() would be.
Keep in mind that MooTools classes are all about extending and reusing existing code. When you extend a class, you might want to change the initialization, but not the setup code. Of course you can run the parent initializer by using this.parent(), but that might introduce unwanted side-effects.
Take this (very simple) example (view live):
var Counter = new Class({
initialize: function(i){
this.i = i;
this.setup();
},
setup: function(){
new Element('p', {
'text': this.i
}).inject(document.body);
}
});
var MultiplyCounter = new Class({
Extends: Counter,
initialize: function(i){
this.i = i * 2;
this.setup();
}
});
new Counter(5);
new MultiplyCounter(5);
The extended class only changes the initialization of i, not the whole implementation of the class. For more complex classes, this creates faster (initialization is only run once) and cleaner (divide and conquer) code.
When developing in ActionScript 3, I often find myself looking for a way to achieve something similar to what is offered by python's __getattr__ / __setattr__ magic methods i.e. to be able to intercept attribute lookup on an instance, and do something custom.
Is there some acceptable way to achieve this in ActionScript 3? In AS3 attribute lookup behaves a little differently for normal (sealed) and dynamic classes -- ideally this would work in the same way for both cases. In python this works beautifully for all kinds of objects (of course!) even for subclasses of dict itself!
Look a the flash.utils.Proxy object.
The Proxy class lets you override the
default behavior of ActionScript
operations (such as retrieving and
modifying properties) on an object.
In AS3 you can code explicit variables accessors.
Example Class1:
private var __myvar:String;
public function get myvar():String { return __myvar; }
public function set myvar(value:String):void { __myvar = value; }
Now as you create an instance of Class1 you can access __myvar through the accessor functions.
if you want to set bindable that var you have to put the [Bindable] keyword upon one of its accessors.
Further, you can also implement the getter or the setter only, so your var will be read or write only.
I hope it helps.