ko.utils.extend Doesn't Override Property From Model - javascript

Why ko.utils.extend doesn't override this.selectItem ? Here it always shows alert of 1.
var ViewModel = function () {
this.selectItem = function () { alert(1) };
};
}
ko.utils.extend(ViewModel.prototype, {
selectItem: function () {
alert("from extend");
}

The reason extend doesn't override it is that it's not a prototype property. It's a property added to the instance by the constructor function, which shadows (hides) the prototype property.
Here's the order of what occurs (note - I've fixed the syntax errors in the code in the question, and added an instantiation of the view model):
// 1 - the `ViewModel` function is created, along with `ViewModel.prototype`
var ViewModel = function () {
// 4 - the instance gets its own `selectItem` property
this.selectItem = function () { alert(1) };
};
// 2 - `selectItem` is added to `ViewModel.prototype`
ko.utils.extend(ViewModel.prototype, {
selectItem: function () {
alert("from extend");
}
});
// 3 - an instance is created; its underlying prototype is set from `ViewModel.prototype`
var vm = new ViewModel();

Related

Is it more efficient to use a common empty function instead of creating a new one in each class instance?

Let's say I have a class that is designed to have some callbacks added to it later on.
function myclass() {
this.onSomething = function () {};
this.onOtherThing = function () {};
this.something = function () {
// stuff
this.onSomething();
};
this.otherThing = function () {
// other stuff
this.onOtherThing();
};
}
I can't have this.onSomething and this.onOtherThing being undefined or null because when they are called in something() and otherThing(), an error will be thrown, stating that their type is not a function.
Since those empty functions are needed, but they use memory, is the class going to be more memory efficient if I did this?
function myclass() {
this.onSomething = empty;
this.onOtherThing = empty;
...
}
function empty() {
}
This way each class instance's properties point to the same empty function, instead of creating new functions every time. I assume defining an empty method doesn't take a lot of memory, but still... is this technically better?
You are right about the fact that a new function is created for every instance of your class. In order to have this shared across all instances you can declare it on the prototype of the class:
var MyClass = function() {
this.something = function () {
// stuff
this.onSomething();
};
this.otherThing = function () {
// other stuff
this.onOtherThing();
};
}
MyClass.prototype.onSomething = function() {};
MyClass.prototype.onOtherThing = function() {};
This way, the methods will be shared by all instances.
why don't you try to return true or return false instead of returning empty functions.
or best you can use :
function myclass() {
this.onSomething = false;
this.onOtherThing = false;
...
}
as per your comment you can try :
function myclass() {
this.onSomething = empty();
this.onOtherThing = empty();
... }
function empty() {
//return something
return true;
}

How can I initialize a new object inside a construction function so that each of its function can reuse it?

function x() {
var obj1 = new ErrorPrinter();
}
x.prototype = {
xFunction1 : function() {
return obj1.printthis("x");
},
xFunction2 : function() {
return obj1.printthis("y");
}
}
But when I do the above, it wont work. The whole purpose of initializing the object on top is the so that I don't have to recreate the same object in each function(xFunction1 and xFunction2).
Thx for such a wonderful community, stackoverflow.com.
Declaring a variable as you did will only make it available inside the constructor function itself, not other functions on the prototype.
On the other hand, if you were to set this.obj1 = ... in the constructor, it would be available as this.obj1 in the other prototype methods when they are called on an instance.
function X() {
this.obj1 = new ErrorPrinter();
}
X.prototype = {
xFunction1: function() {
return this.obj1.printthis("x");
},
xFunction2: function() {
return this.obj1.printthis("y");
}
};

Prototype js super method call or something like this

Prototype js allows to call super method by $super. I need call class-method from object, but in overriden method, like this:
var ClassA = Class.Create({
initialize: function(options) {
Object.extend(this, options);
},
method1: function(){/*some code*/}
});
var ClassB = Class.Create(ClassA, {
method1: function($super) {
$super(); // this works fine, calls ClassA.method1()
}
});
var objectA = new ClassA({
method1: function($super) { // I need something like this
$super(); // this not works, must calls ClassA.method1()
}
});
How can I do this?
If you want just objectA to have the new method, do this:
var objectA = new ClassA();
objectA.method1 = objectA.method1.wrap(function (fn) {
fn(); // works like a `$super` call inside of a class
});
It uses Function#wrap to add advice around the function.
If you need to pass arguments to the function, do this:
var objectA = new ClassA();
objectA.method1 = objectA.method1.wrap(function () {
var args = $A(arguments), fn = args.shift();
fn(args); // works like a `$super` call inside of a class
});
If you want to redefine the method in an already defined Class you need to use Class#addMethods
var ClassA = Class.Create({
initialize: function(options) {
Object.extend(this, options);
},
method1: function(){/*some code*/}
});
ClassA.addMethods({
method1: function() {
/** does something else **/
}
});
However this will overwrite the method1 method and not create a subclass or child method of the original one
http://api.prototypejs.org/language/Class/prototype/addMethods/
For my needs I find next decision:
function singleton() {
var AnonymousClass = Class.create.apply(Class, arguments);
return new AnonymousClass();
}
This function get me chance to override any method in class.
Example
singleton(ClassA, {
method1: function($super) {
/* call of $super() */
}
})
This work for me as I wanted. Function returns for me object with overrided method from class, but this method can calls $super.

Object Not Defined with Knockout Data Mapping Plugin

I'm trying to use the mapping plugin to make children objects' properties observable. I have the following:
// setData defined here
var mapping = {
create: function(options) {
//customize at the root level.
var innerModel = ko.mapping.fromJS(options.data);
innerModel.cardCount = ko.computed(function () {
debugger;
return this.cards().length; // cards not defined - "this" is Window for some reason
});
innerModel.deleteCard = function (card) {
// Pending UI
// call API here
// On success, complete
this.cards.remove(card);
}.bind(this);
innerModel.addCard = function () {
//debugger;
// Pending UI
// Call API here
// On success, complete
this.cards.push(dummyCard);
//this.cardToAdd("");
}.bind(this);
return innerModel;
}
};
var SetViewModel = ko.mapping.fromJS(setData, mapping);
ko.applyBindings(SetViewModel);
When I run this in chrome debugger, I get "Object [Object global] has no method cards". Cards should be an observable array. What am I doing wrong?
innerModel.cardCount = ko.computed(function () {
debugger;
return this.cards().length; // cards not defined - "this" is Window for some reason
});
this is inside the anonymous function you're creating and is therefore bound to the global object. if you want to reference innermodel you'll have to do so directly, or bind innermodel to the function.
innerModel.cardCount = ko.computed(function () {
return innerModel.cards().length;
});
or
var computedFunction = function () {
return this.cards().length;
};
innerModel.cardCount = ko.computed(computedFunction.apply(innerModel));

Javascript inheritance and method overriding

Assume I have a class like this:
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
}
}
From this class I created some other classes which inherit the same prototype but have some added methods. What I want to do is being able to define a load() method in the sub-classes which first calls the parent method and then execute some code. Something like:
SpecialWidget.prototype = {
load: function(args) {
super.load(args);
// specific code here
}
}
I know there's no super keyword in Javascript but there must be a way to do this.
You can simulate it like this:
SpecialWidget.prototype = {
load: function(args) {
Widget.prototype.load.call(this, args);
// specific code here
}
}
Or you can create your own super property like this:
SpecialWidget.prototype.parent = Widget.prototype;
SpecialWidget.prototype = {
load: function(args) {
this.parent.load.call(this,args);
// specific code here
}
}
so first, you set up your 'subclass' like so
function SubClass(name) {
Super.call(this);
// stuff here
}
SubClass.prototype = new SuperClass(null);
SubClass.prototype.constructor = SubClass;
and then you can do
SuperClass.prototype.theMethod.apply(this);
from within a subclass implementation to specifically invoke the super's implementation.
I don't know if this is the best solution, but you could do something like this:
function Widget() {
this.id = new Date().getTime();
}
Widget.prototype.load = function(args) {
alert( 'parent load' );
};
SpecialWidget = function(){};
// Make the prototype of SpecialWidget an instance of Widget
var proto = SpecialWidget.prototype = new Widget;
// Give the prototype a function that references the "load" from Widget
proto.parent_load = proto.load;
// Give SpecialWidget its own "load" that first calls the parent_load
proto.load = function( args ) {
this.parent_load( args );
alert( 'special load' );
};
var inst = new SpecialWidget;
inst.load();
This makes the prototype of SpecialWidget an instance of Widget so that it inherits all that Widget has.
Then it makes a reference to the load() of Widget called parent_load(), and creates its own load() that calls the parent_load() when invoked.
Since mid-2015 (ECMAScript 2015), javascript has Classes and super
Here's the link: https://262.ecma-international.org/6.0/, see section 12.3.5 (super) and 14.5 (Class definitions).
How your code would look with those changes:
class Widget() {
constructor() {
this.id = new Date().getTime();
// other fields
}
load(args) {
// do something
}
}
class SpecialWidget extends Widget {
load(args) {
super.load(args);
// specific code here
}
}
The closest I got to the previous syntax (without using class but using super) was using Object.setPrototypeOf:
// UNCHANGED
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
}
}
// slightly changed to declare SpecialWidget
function SpecialWidget() {}
// changed to define load as an method, and not a property with function as value
SpecialWidget.prototype = {
load(args) {
super.load(args);
// specific code here
}
}
// here's the key
Object.setPrototypeOf(SpecialWidget.prototype, Widget.prototype);
The declaration of load was changed because super can be used inside methods, but not functions. So, instead of load: function(args) { body }, it's simply load(args) { body }.
But, there's a caveat: with this solution, elements of SpecialWidget will not inherit the id defined as new Date().getTime(). I don't think there's a workahound (without using classes or duplicating code declaring this.id inside SpecialWidget).
It would be possible to store the old value of the load method in a closure, if you did your overriding like this:
function Widget() {
this.id = new Date().getTime();
// other fields
}
Widget.prototype = {
load: function(args) {
// do something
alert("Widget Prototype Load");
}
};
function SpecialWidget(){
};
SpecialWidget.prototype = new Widget();
(function(){
var oldLoad = SpecialWidget.prototype.load;
SpecialWidget.prototype.load = function(){
oldLoad();
alert("new Load");
};
}());
var x = new SpecialWidget();
x.load();
It works, but I'm not sure if it's the best method.
Using Simple Javascript Class:
Class.extend('Widget', {
load: function () {
alert('foo');
}
});
Widget.extend('SpecialWidget', {
load: function () {
this.super();
alert('bar');
}
});
new Widget().load(); // Alert: 'foo'
new SpecialWidget().load(); // Alert: 'foo' and 'bar'
Take a look at Simple Javascript Class Project, Simple JavaScript Inheritance and Inheritance Patterns in JavaScript.

Categories

Resources