I have following pattern
BASE = function () {
var that = {};
var number = 10;
that.showNumber = function(){
that.alertNumber();
}
that.alertNumber = function () {
alert(number);
};
return that;
};
CHILD = function () {
var that = Object.create(BASE());
var secondNumber = 20;
// Override base function
that.alertNumber = function () {
alert(secondNumber);
};
return that;
};
var ch = CHILD();
ch.showNumber();
Can you tell me how can I adjust my module pattern inspired by Douglas CrockFord to fully override alerNumber function? So far showNumber function displays 10 instead of 20.
Thank you all in advanced
JSFiddle with code is here
You could change
that.showNumber = function(){
that.alertNumber();
}
to
that.showNumber = function(){
this.alertNumber();
}
But I'm not sure I see why you don't simply use the prototype-base inheritance model.
Related
I want the array to call one random variable from it but it calls every variable in it and I don't know why.
Code:
var atk1 = Billy.giveLife("self");
var atk2 = Billy.punch("self");
var attack = [atk1,atk2];
function test(){
var r = Math.round(Math.random()*(attack.length-1));
attack[r];
}
test();
On your first 2 lines you are immediately calling the functions. attack[r] does nothing, square braces are only for selecting an element from an array.
Here’s one solution to what you might be trying to do, using anonymous arrow functions to store your functions to be called later:
var atk1 = () => Billy.giveLife("self");
var atk2 = () => Billy.punch("self");
var attack = [atk1,atk2];
function test(){
var r = Math.round(Math.random()*(attack.length-1));
attack[r]();
}
test();
Okay, I think you are missing braces '()' so I did a little prototype for you, here it is:
http://jsfiddle.net/pvkovalev/e75nx3rn/
I modified your code a little bit to make more visual:
function printf(data) {
$('#out').html($('#out').html() + '<br/>' + data);
}
var atk1 = function() {
printf('atk1');
}
var atk2 = function() {
printf('atk2');
}
var atk3 = function() {
printf('atk3');
}
var atk4 = function() {
printf('atk4');
}
var atk5 = function() {
printf('atk5');
}
var attack = [atk1, atk2, atk3, atk4, atk5];
function test() {
var r = Math.round(Math.random() * (attack.length - 1));
attack[r]();
}
setInterval(function() {
test();
}, 1500)
Why would this inside function be undefined in angularjs service?
.service('SliceService', function () {
var self = this;
var Slice = function(intervals, intervalSpan) {
self.activeSlice = [];
self.hasNext = true;
self.hasPrevious = false;
self.intervals = intervals;
self.intervalSpan = intervalSpan;
}
Slice.prototype.findIntervalIndex = function (time, slice) {
slice = slice || self.intervals;
return _.findIndex(slice, function (o) {
return o.time === time;
});
};
return Slice;
})
.controller('myController', ['SliceService', function(SliceService) {
SliceService([arr], 12);
SliceService.findINtervalIndex(time);
}])
In the above example when using it in a controller, this.activeSlice throws an error TypeError: Cannot set property 'activeSlice' of undefined.
-
Update
Thanks, everyone! I've updated my example to better reflect what I'm trying to do. With the above I'm getting a TypeError: SliceService.findIntervalIndex is not a function — Also maybe a service is not fit for what I'm trying to do?
Try saving the value of "this" before accessing it inside the anonymous scope:
(function(){
'use strict';
angular.module('myServices').service('SliceService', function () {
var context = this;
var Slice = function(intervals, intervalSpan) {
context.activeSlice = [];
context.hasNext = true;
context.hasPrevious = false;
context.intervals = intervals;
context.intervalSpan = intervalSpan;
}
return Slice;
});
}());
Using Bind:
angular.module('myServices').service('SliceService', function () {
var Slice = function(intervals, intervalSpan) {
this.activeSlice = [];
this.hasNext = true;
this.hasPrevious = false;
this.intervals = intervals;
this.intervalSpan = intervalSpan;
}.bind(this);
return Slice;
});
Note:
using arrow function of javascript ES6 makes sure that this always points to the same context. so you could replace regular function with arrow function. This is however not universally supported without transpiling.
service('SliceService', ()=>{
// operations
}
Thanks to #SeedyROM and some additional google searches on angular services. This solved all my issues...
angular.module('vpower.services').service('SliceService', function () {
this.activeSlice = [];
this.hasNext = true;
this.hasPrevious = false;
this.intervals = [];
this.intervalSpan = 12;
this.findIntervalIndex = function (time, slice) {
var curTime;
slice = slice || this.intervals;
return _.findIndex(slice, function (o) {
curTime = o.time._i || o.time;
return curTime === time;
});
};
I think I was not fully understanding the way services work.
This is driving me crazy. I'm about to break down and cry.
Here's my code that is NOT working:
// parent class: Shirt
var Shirt = function() {
this.basePrice = 1;
}
Shirt.prototype.getPrice = function(){return this.basePrice};
Shirt.prototype.display = function(){
$('ul#products').append('<li>Product: $' + this.getPrice() + '.00</li>');
};
// subclass: ExpensiveShirt inherits from Shirt
var ExpensiveShirt = function() {
this.basePrice = 5;
};
ExpensiveShirt.prototype = Object.create(Shirt);
// make some objects and test them
var s = new Shirt();
s.display(); // this works
console.log(s.getPrice()); // this works
var e = new ExpensiveShirt();
e.display(); // this does not work!
console.log(e.getPrice()); // does not work
HERE IS THE JSFIDDLE
Now, if I add these lines, then it works:
ExpensiveShirt.prototype.getPrice = Shirt.prototype.getPrice;
ExpensiveShirt.prototype.display = Shirt.prototype.display;
But according to this I shouldn't have to: JavaScript inheritance with Object.create()?
And I really don't want to because that is bad programming. >:(
Object.create expects the prototype for the new object as its argument, not the constructor. Change your line to this, and it will work:
ExpensiveShirt.prototype = Object.create(Shirt.prototype);
As #Paulpro mentions, you need to use Object.create on Shirt.prototype and not Shirt for inheritance to work.
I usually use the following two functions to make my life easier when dealing with inheritance in JavaScript:
var Shirt = defclass({
constructor: function () {
this.basePrice = 1;
},
getPrice: function () {
return this.basePrice;
},
display: function () {
alert("Product: $" + this.getPrice() + ".00");
}
});
var ExpensiveShirt = extend(Shirt, {
constructor: function () {
this.basePrice = 5;
}
});
var s = new Shirt;
var e = new ExpensiveShirt;
s.display();
e.display();
console.log(s.getPrice());
console.log(e.getPrice());
<script>
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function extend(constructor, properties) {
var prototype = Object.create(constructor.prototype);
for (var key in properties) prototype[key] = properties[key];
return defclass(prototype);
}
</script>
Hope that helps.
I have a Constructor function "Animals", that is namespacing some other Constructor functions, "Crocodile" and "Monkey":
var Monkey = function(Animals) {
this.Animals = Animals;
};
Monkey.prototype.feedMe = function() {
this.Animals.feed();
};
var Crocodile = function(Animals) {
this.Animals = Animals;
};
Crocodile.prototype.feedMe = function() {
this.Animals.feed();
};
var Animals = function(zoo) {
this.zoo = zoo;
};
Animals.prototype.feed = function() {
//feed the animal
};
Animals.prototype.Monkey = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Monkey.prototype = Monkey.prototype;
Animals.prototype.Crocodile = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Crocodile.prototype = Crocodile.prototype;
With the intention that I should be able to do the following:
var animals = new Animals("NY");
var monkey = new animals.Monkey();
monkey.feed();
I'm receiving an error that says that monkey.feed() is not a function. I'm assuming i'm doing something wrong with the way i'm inheriting the Monkey function inside the Animal constructor function but for the life of me I haven't been able to find the solution.
What is the correct method I should be using to namespace these functions?
I have seen quite some stuff, but abusing prototypes for namespaces, what the heck. What's wrong with a nice and simple:
var Animals = {
Crocodile: {
}
}
Or if you want the constructor way:
var Animals = function () {
return {
Crocodile: function () {}
}
};
var a = new Animals();
var c = new a.Crocodile();
I'm trying to understand pure prototype-based JavaScript and one specific thing I'm struggling with is reuse (inheritance).
For my project I landed this way of creating objects that can be reused.
// very generic prototype
var Apparatus = (function(){
var self = Object.create({});
self.state = false;
self.on = function() { this.state = true; };
return self;
})();
// more specific prototype
var Radio = (function(){
var self = Object.create(Apparatus);
self.frequency = 0;
self.setFrequency = function(f) { this.frequency = f; }
self.getFrequency = function() { return this.frequency; }
return self;
})();
I then want to "instantiate"/copy the Radio object, creating two different radios.
var kitchenRadio = Object.create(Radio);
kitchenRadio.state = false;
kitchenRadio.on();
var carRadio = Object.create(Radio);
carRadio.state = false;
console.log(kitchenRadio.state, carRadio.state);
// true false
This works, but will it continue to? Can anyone predict any unwanted outcomes?
Like #pimvdb said, remove state and this works well.
// very generic prototype
var Apparatus = (function(){
var self = Object.create({});
self.on = function() { this.state = true; };
return self;
})();
// more specific prototype
var Radio = (function(){
var self = Object.create(Apparatus);
self.setFrequency = function(f) { this.frequency = f; }
self.getFrequency = function() { return this.frequency; }
return self;
})();
I then use Object.create(Object, params) to instantiate it.