implementing extend method in javascript - javascript

By looking through the code of BackboneJS, i am interested about extend the implemented. by when i try to make it myself i am stuck. my code is the following.
var extend = function(child) {
var base = this;
if(child) {
for(var prop in child) {
base[prop] = child[prop];
}
}
return base;
};
var Test = Mod.Test = function() {
this.data = {};
}
Test.prototype.set = function(key, value) {
this.data[key] = value;
}
Test.prototype.get = function(key) {
return this.data[key];
}
Test.extend = extend;
when i try like this i am not able to attach hello method to Mod.Test
var testObj = new Mod.Test.extend({
hello : function() {
console.log('hello');
}
});
How is it possible. how its implemented in backbonejs.

Backbone's extend method accepts two parameters - instance properties and static properties. The first ones are copied to the instance being created, the second are assigned to the instance's prototype. Usually you should invoke the extend method without the new operator but in this case here is a working version of your code:
var extend = function(child) {
var base = this;
if(child) {
for(var prop in child) {
base[prop] = child[prop];
}
for(var prop in child) {
base.prototype[prop] = child[prop];
}
}
return base;
};
var Test = Backbone.Model.Test = function() {
this.data = {};
}
Test.prototype.set = function(key, value) {
this.data[key] = value;
}
Test.prototype.get = function(key) {
return this.data[key];
}
Test.extend = extend;
and then:
Test = Backbone.Model.Test.extend({
hello : function() {
console.log('hello');
}
});
var testObj = new Test;

Related

Can't enumerate getters/setters properties

I am working on some reflections code to try to scrape out properties and functions, but I can't seem to get the getters/setters at all.
The reflection code I have for properties is:
Reflector = function() { };
Reflector.getProperties = function(obj) {
var properties = [];
var proto = obj;
while (proto != Object.prototype) {
console.log('Scrapping proto: ', proto);
for (var prop in proto) {
console.log('typeof ' + prop + ": ", typeof obj[prop]);
if (typeof obj[prop] != 'function') {
properties.push(prop);
}
}
proto = Object.getPrototypeOf(proto);
}
return properties;
};
And a sample of it running (with my debug messages) is:
var SimpleTestObject = function() {
this.value = "Test1";
this._hiddenVal = "Test2";
this._readOnlyVal = "Test3";
this._rwVal = "Test4";
};
SimpleTestObject.prototype = {
get readOnlyVal() {
return this._readOnlyVal;
},
get rwVal() {
return this._rwVal;
},
set rwVal(value) {
this._rwVal = value;
},
func1: function() {
// Test
}
};
SimpleTestObject.func2 = function(test) { /* Test */ };
SimpleTestObject.outsideVal = "Test5";
var props = Reflector.getProperties(SimpleTestObject);
console.log('props: ', props);
console.log('Object.getOwnPropertyNames: ', Object.getOwnPropertyNames(SimpleTestObject));
console.log('rwVal property descriptor: ', Object.getOwnPropertyDescriptor(SimpleTestObject, 'rwVal'));
console.log('rwVal (2) property descriptor: ', Object.getOwnPropertyDescriptor(Object.getPrototypeOf(SimpleTestObject), 'rwVal'));
What I expect to see as output to my Reflection.getProperties(SimpleTestObject) is ['readOnlyVal', 'rwVal', 'outsideVal'], but instead I am only seeing outsideVal. Further, when I tried to using getOwnPropertyDescriptor() to see if the rwVal was enumerable, it came back as undefined. So, thinking maybe it somehow got showed into the prototype above, I tried going up a level and still got undefined.
For enumerate the getters please use Object.keys or Object.getOwnPropertiesNames on prototype instead of constructor or/and instance:
function readGetters(obj) {
var result = [];
Object.keys(obj).forEach((property) => {
var descriptor = Object.getOwnPropertyDescriptor(obj, property);
if (typeof descriptor.get === 'function') {
result.push(property);
}
});
return result;
}
var SimpleTestObject = function() {
this.value = "Test1";
this._hiddenVal = "Test2";
this._readOnlyVal = "Test3";
this._rwVal = "Test4";
};
SimpleTestObject.prototype = {
get readOnlyVal() {
return this._readOnlyVal;
},
get rwVal() {
return this._rwVal;
},
set rwVal(value) {
this._rwVal = value;
},
func1: function() {
}
};
SimpleTestObject.func2 = function(test) { /* Test */ };
SimpleTestObject.outsideVal = "Test5";
// For constructor
console.log(readGetters(SimpleTestObject.prototype));
// For instance
var instance = new SimpleTestObject();
console.log(readGetters(Object.getPrototypeOf(instance)));
you can enumerate setter/getter properties by Object.getOwnPropertyNames if you use getter and setter with Object.defineProperty or Object.defineProperties
const _name = Symbol();
const _age = Symbol();
class Dog {
constructor(name, age) {
Object.defineProperties(this, {
name: {
// you can set enumerable true explicitly if you want
//enumerable:true ,
set(value) {
this[_name] = name;
},
get() {
return this[_name];
}
},
age: {
set(value) {
this[_age] = age;
},
get() {
return this[_age];
}
},
book: {
get() {
return "Book"
}
}
});
this.name = name;
this.age = age;
}
}
const dog = new Dog("spike", 3);
console.log(Object.getOwnPropertyNames(dog));

What is wrong with my observable pattern?

I'm testing the observable pattern in javascript. My callbacks in the array never seem to execute. What is wrong with my syntax?
<script type="text/javascript">
var Book = function (value) {
var onChanging = [];
this.name = function () {
for (var i = 0; i < onChanging.length; i++) {
onChanging[i]();
}
return value;
}
this.addTest = function (fn) {
onChanging.push(fn);
}
}
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name = 15;
</script>
From your code above it looks like you need to call your function name instead of assigning a value something like:
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name(); //<-- Before b.name = 15
Setting b.name = 15 doesn't execute the function, it just overwrites the value of b.name.
You could use getters and setters to react to a changing value. See John Resig's blog post or the MDN reference
I edited your code to use them:
var Book = function (value) {
this.onChanging = [];
this._name = "";
}
Book.prototype = {
addTest: function (fn) {
this.onChanging.push(fn);
},
get name() {
return this._name;
},
set name(val) {
for (var i = 0; i < this.onChanging.length; i++) {
this.onChanging[i](val);
}
this._name = val;
}
};
var b = new Book(13);
b.addTest(function (val) {
console.log("executing", val);
return true;
});
b.name = 15;
b.name = 17;
working demo.
You can also make a more generic solution that can work for all your properties without having to define the getters and setters, a lot of frameworks use this approach.
Book = function () {
this._events = [];
this._rawdata = {};
}
Book.prototype = {
bind: function (fn) {
this._events.push(fn);
},
// pass the property, and it returns its value, pass the value and it sets it!
attr: function (property, val) {
if (typeof val === "undefined") return this._rawdata[property];
this._rawdata[property] = val;
for (var i = 0; i < this._events.length; i++)
// we pass out the val and the property
this._events[i](val, property);
}
};
b = new Book();
b.bind(function (val) {
console.log("executing", val);
return true;
});
b.attr("name","The Hobbit");
b.attr("SKU" ,1700109393901);
console.log(b.attr("name")); // --> The Hobbit
http://jsfiddle.net/wv4ch6as/
Of course you would want to change the binder so that you can bind onto properties not one bind for all properties, but I think this gets the idea.

Why is my effort to implement Parasitic Inheritance in Javascript failing here?

I am playing with classical inheritance in Javascript (in Chrome) following the example of Crockford. I like the parasitic interface but am looking for a bit cleaner way to encapsulate inheritance.
There are a couple additional requirements I am trying to meet:
I'd like to be able to override methods of the parent class with methods in the child class that can call the parent method
I don't want to have to re-declare properties of the parent class in the child class.
This is my parent class Parasite with an extend method that tries to encapsulate inheritance and take advantage of Object.defineProperty:
function Parasite(host) {
var self = {};
self.host = host;
self.swollen = false;
self.init = function() {
console.debug('Parasite.init');
return self;
};
self.suck = function() {
console.log("I'm a parasite who sucks on " + self.host);
self.swollen = true;
return self;
};
self.extend = function(child) {
for(var prop in self) {
if (prop == 'extend') { // skip extend
console.debug('skip extend');
continue;
}
var is_extended = child.hasOwnProperty(prop);
var is_accessor = typeof self[prop] != "function";
// inherit prop
if (! is_extended) {
child[prop] = self[prop];
console.debug('prop', prop, 'inherited by child');
}
// default: override
else {
console.debug('prop', prop, 'overridden by child');
}
// For accessors, parent should reference child. This tries to
// synchronize them on the child's accesor.
if (is_accessor) {
var accessor = prop.toString();
console.warn('define accessor for', accessor, ':', child[accessor]);
Object.defineProperty(self, accessor, {
get: function() {
var val = child[accessor];
console.debug('getting', accessor, val, 'from', child, 'for', self);
return val;
},
set: function(val) {
console.debug('setting', accessor, val, 'from', child, 'for', self);
child[accessor] = val;
},
enumerable: true,
configurable: true
});
};
}
child.parent = self;
return child;
};
self = self.init();
return self;
}
This is my child class, Tick:
function Tick(host) {
var self = {};
self.suck = function() {
self.parent.suck.call();
self.engorge();
};
self.engorge = function() {
console.log("And now I'm engorged with blood.");
};
self.init = function() {
var parent = new Parasite(host);
self = parent.extend(self);
return self;
};
self = self.init();
return self;
}
You can find my latest fiddle here (warning: infinitely recurses in Firefox, but not in Chrome):
http://jsfiddle.net/SSDgv/23/
The console output illustrates where the accessor issues are occurring.
This isn't an answer to my question, per se, but here's a much simpler implementation that seems to meet my requirements. It follows the pattern presented in this Stack Overflow answer.
function Parasite(host) {
var self = {};
self.host = host;
self.hungry = true;
self.init = function() {
console.debug('Parasite.init');
return self;
};
self.suck = function() {
console.log("I'm a parasite who sucks on " + self.host);
self.hungry = false;
return self;
};
self.init();
return self;
}
function Tick(host) {
var self = new Parasite(host);
self.engorged = false;
var base_suck = self.suck;
self.suck = function() {
base_suck();
self.engorge();
};
self.engorge = function() {
console.log("And now I'm engorged with blood.");
self.engorged = true;
};
self.init = function() {};
self.init();
return self;
}
Fiddle with tests can be found here: http://jsfiddle.net/AvdK2/3/

Copy object properties in JavaScript

I have some custom Object definitions like:
var Class1 = function () { this.value = ''; };
var Class2 = function () { this.data = ''; };
Class1.prototype = {
setObject: function () {
for (var prop in this){
if (typeof obj[prop] != 'undefined')
this[prop] = obj[prop];
}
}
}
Class2.prototype = {
setObject: function () {
for (var prop in this){
if (typeof obj[prop] != 'undefined')
this[prop] = obj[prop];
}
}
}
Is there a way to have this method setObject by default to all clases?
Is it better to (simulate) inherit that function from the Object type in JavaScript or is it better to use a global function or to define it one by one?
If you're going to be using a library such as jQuery or underscore, you'll already have access to a resilient extend method (see $.extend, and _.extend), so I would say that there's no reason to reinvent the wheel on these custom object types.
Otherwise, you can have Class1 and Class2 inherit from a common base class:
function BaseClass() {
...
}
BaseClass.prototype = {
setObject: function (obj) {...}
};
function Class1() {
...
}
Class1.prototype = new BaseClass();
function Class2() {
...
}
Class2.prototype = new BaseClass();
var a = new Class1();
a.setObject({...});
var b = new Class2();
b.setObject({...});
Or, if those objects should not contain a common ancestor, you could define them to use the same setObject function reference:
function setObject(obj) {
...
}
function Class1() {
...
}
Class1.prototype = {
setObject: setObject
};
function Class2() {
...
}
Class2.prototype = {
setObject: setObject
}
I am not sure if you know that, but there are no classes or methods in Javascript. There are only objects, functions and a special property called "prototype".
The common way of simulating classes is this:
var Class = function () { this.prop = "hi" };
Class.prototype.doMethod = function () { this.prop = "hi2"; };
Class.prototype.setObject: function () {
for (var prop in this){
if (typeof obj[prop] != 'undefined')
this[prop] = obj[prop];
}
}
// those classes "inherit" from Class
var Class1 = function () { Class.call(this); this.value = ''; };
Class1.prototype = new Class();
var Class2 = function () { Class.call(this); this.data = ''; };
Class2.prototype = new Class();
Ivan showed how to inherit from an object. More information about using constructor functions and inherritance can be found here: Prototypical inheritance - writing up
You can use a mixin pattern as well:
var mixIn=function(target,source){
for(fn in source){
if(source.hasOwnProperty(fn)){
target.prototype[fn]=source[fn];
}
}
};
var ObjectSettable = {
setObject: function () {
for (var prop in this){
if (typeof obj[prop] != 'undefined')
this[prop] = obj[prop];
}
}
};
var Class1 = function () { this.value = ''; };
//... Class1.prototype stuff
mixIn(Class1,ObjectSettable);

encapsulation in javascript module pattern

I was reading this link http://addyosmani.com/largescalejavascript/#modpattern
And saw the following example.
var basketModule = (function() {
var basket = []; //private
return { //exposed to public
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
It stats that "The module pattern is a popular design that pattern that encapsulates 'privacy', state and organization using closures" How is this different from writing it like the below? Can't privacy be simply enforced with function scope?
var basketModule = function() {
var basket = []; //private
this.addItem = function(values) {
basket.push(values);
}
this.getItemCount = function() {
return basket.length;
}
this.getTotal = function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
var basket = new basketModule();
basket.addItem({item:'bread',price:0.5});
basket.addItem({item:'butter',price:0.3});
In the first variant you create an object without the possibility to create new instances of it (it is an immediately instantiated function). The second example is a full contructor function, allowing for several instances. The encapsulation is the same in both examples, the basket Array is 'private' in both.
Just for fun: best of both worlds could be:
var basketModule = (function() {
function Basket(){
var basket = []; //private
this.addItem = function(values) {
basket.push(values);
}
this.getItemCount = function() {
return basket.length;
}
this.getTotal = function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
return {
basket: function(){return new Basket;}
}
}());
//usage
var basket1 = basketModule.basket(),
basket2 = basketModule.basket(),

Categories

Resources