I have a class setup as follows:
var oTest = new TEST();
function TEST() {
this.String = function(sString) {
this.Trim = function() {
}
}
}
I want to be able to call the Trim function as follows:
var sTrimmed = oTest.String(" something").Trim();
Is this the correct approach? Any help would be greatly appreciated as i have never done functions inside class functions before.
Add your methods to the prototype of the constructor function, and do return this; in String, to return the same object, which makes it chainable.
var oTest = new TEST();
function TEST() {}
TEST.prototype.String = function(aString) {
this.the_string = aString;
return this;
};
TEST.prototype.Trim = function() {
this.the_string = this.the_string.trim();
return this;
};
TEST.prototype.getString = function() {
return this.the_string;
};
var sTrimmed = oTest.String(" something")
.Trim()
.getString();
live demo: http://jsfiddle.net/BcwgC/
Related
Why it doesn't work? When I'm trying to call example.example() I'm getting TypeError: example.example is not a function.
var example = class {
constructor(){
this.example = false;
}
id(){
this.example = !this.example;
return this.example;
}
};
When I'm trying to call example.example() I'm getting TypeError:
example.example is not a function.
example is a reference to an anonymous class, and its constructor can only be invoked with new
You need to call it as
var a = new example();
a.example; //false
Demo
var example = class {
constructor() {
this.example = false;
}
id() {
this.example = !this.example;
return this.example;
}
};
var a = new example()
console.log(a.example);
You have created class so you need to make an object of this.It should work by calling like this.
var example = class {
constructor(){
this.example = false;
}
id(){
this.example = !this.example;
return this.example;
}
};
console.log((new example()).id());
var obj = new example();
console.log(obj.id());
Let's say I have a function like the one below that creates a very simple micro-library:
var microLib = function(selector) {
var el;
var selectorEngine = function(selector)
{
var selector_value = selector.slice(1);
return document.getElementById(selector_value);
};
el = selectorEngine(selector);
Element.prototype.func_1 = function(){
return 'first';
};
Element.prototype.func_2 = function(){
return 'second';
};
return el;
};
window._$ = microLib;
This script will allow me to write code like this:
var elem = _$("#div_with_id"); //some element on my web page
console.log(elem.func_2()); //outputs 'second' in the console
So now, I'm looking for a way to extend _$ in a supplementary piece of code to add additional Element.prototype methods, which will allow me to write:
console.log(elem.func_3()); //to output 'third' in the console
The reason I need to do this is because this extension needs to take place in another JavaScript file, otherwise I would I have just added another method and be done with it.
How can I do this?
Here's an example of the approach that I am suggesting: http://jsfiddle.net/rbxssmx8/.
JS:
var toArray = Function.prototype.call.bind(Array.prototype.slice);
var qAll = document.querySelectorAll.bind(document);
var _$ = (function() {
function dom(selector) {
if(!(this instanceof dom)) {
return new dom(selector);
}
this.elements = toArray(qAll(selector));
}
dom.prototype.iterate = function(func) {
this.elements.forEach(func);
return this;
};
dom.prototype.addClass = function() {
var klasses = arguments;
return this.iterate(function(element) {
element.classList.add.apply(element.classList, klasses);
});
};
dom.extend = function(name, func) {
this.prototype[name] = func;
};
dom.ready = function(func) {
document.addEventListener("DOMContentLoaded", func);
};
return dom;
})();
_$.extend("removeClass", function() {
var klasses = arguments;
return this.iterate(function(element) {
element.classList.remove.apply(element.classList, klasses);
});
});
_$("div").addClass("gray");
var $el = _$("div:last-of-type");
$el.removeClass("gray");
So I read this post on What's wrong with extending the DOM and the alternative suggested by the author was to use Object Wrappers. A quick search on that led me to this post on SO: Using object wrappers to extend the JavaScripts DOM?
Coupled with some insight from #DRD's answer, I updated my code:
(function() {
var microLib = function (selector){
return new Dom(selector);
};
function Dom(selector)
{
var selector_value = selector.slice(1);
this.element = document.getElementById(selector_value);
}
Dom.prototype.func_1 = function(){
return 'first';
};
Dom.prototype.func_2 = function(){
return 'second';
};
microLib.extend = function(name, func){
Dom.prototype[name] = func;
};
window._$ = microLib;
})();
And then whenever you want to extend and add another function, do this afterwards:
_$.extend('func_3', function(){ //this is inline with my earlier question
return 'third';
});
Works like a charm! And definitely the safer option compared to extending Element.prototype.
I'm new in programming and I'm learning JavaScript OOP, trying to make a game with tanks. I have some code but it doesn't work properly and I need some help to understand how it works. Please check it and tell me how to solve the problem because I want to add a few more kinds of tanks but before that I need to fix the code.
var Tank = (function () {
function Tank(name) {
this._name = name;
}
Tank.prototype.getWeight = function () { return this._weight; }
Tank.prototype.getName = function () { return this._name; }
return Tank;
}());
var SmallTank = (function () {
this.prototype = Object.create(Tank.prototype);
function SmallTank(name) {
Tank.apply(this._name);
}
SmallTank.prototype._weight = 2;
return SmallTank;
}());
var myTank = new SmallTank("Aleks Tank");
console.log(myTank.getWeight());
It seems that you're just trying to do some kind of inheritance; typically you do this by assigning a parent instance to the prototype of the child.
I think you will want something like this:
var SmallTank = (function () {
function SmallTank(name) {
Tank.call(this, name);
this._weight = 2;
}
SmallTank.prototype = new Tank();
return SmallTank;
}());
Alternatively you can assign Object.create(Tank.prototype).
Here is another way of doing what it looks like you are attempting to do, following the Mozilla guide:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
var Tank = function (name) {
this.name = name;
};
Tank.prototype.getName = function () { return this.name; };
var SmallTank = function (name) {
Tank.call(this, name);
this.weight = 2;
};
SmallTank.prototype = Object.create(Tank.prototype);
SmallTank.prototype.constructor = SmallTank;
SmallTank.prototype.getWeight = function () { return this.weight; };
var myTank = new SmallTank("Aleks Tank");
console.log(myTank.getName());
console.log(myTank.getWeight());
Is it possible to call parent method in JavaScript class but to still have access to prototype methods from parent and child class. Here is code example:
var Base = function() {
this.baseMethod = function(){
return 'baseMethod';
};
this.baseInitMethod = function() {
return 'baseInitMethod';
}
}
Base.prototype.basePrototypeMethod = function() {
return "basePrototypeMethod";
};
var Specific = function() {
Base.call(this);
this.baseInitMethod = function() {
// call baseInitMethod from Base class
}
this.specificMethod = function(){
return 'specificMethod';
}
this.specificInitMethod = function() {
return this.basePrototypeMethod();
}
}
Specific.prototype.specificPrototypeMethod = function() {
return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}
for(var p in Base.prototype) {
Specific.prototype[p] = Base.prototype[p]
}
var s = new Specific();
console.log(s.baseMethod());
console.log(s.baseInitMethod());
console.log(s.basePrototypeMethod());
console.log(s.specificMethod());
console.log(s.specificInitMethod());
console.log(s.specificPrototypeMethod());
I want to call baseInitMethod in Base class from baseInitMethod method inside Specific class but so that all function calls from above still works. Is that possible?
Your Specific.prototype object should inherit from the Base.prototype object. Currently you're copying over all its properties to the object with this code:
for(var p in Base.prototype) {
Specific.prototype[p] = Base.prototype[p]
}
But you should actually use Object.create to establish a real prototype chain:
Specific.prototype = Object.create(Base.prototype);
Specific.prototype.specificPrototypeMethod = function() {
return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}
I want to call baseInitMethod in Base class from baseInitMethod method inside Specific class
Yes. In your Specific constructor, you first need get Base's baseInitMethod instance method, before you overwrite the property of the instance:
function Specific() {
Base.call(this);
var parentInitMethod = this.baseInitMethod;
this.baseInitMethod = function() {
// call baseInitMethod from Base class:
parentInitMethod.call(this /*, arguments…*/);
}
…
}
so that all function calls from above still works.
I'm not sure what you mean by that exactly. The specificPrototypeMethod will always call the baseInitMethod of the current instance, which would be Specific's overwritten one not the original that was defined in Base.
Here is what you need to do:
var Base = function () {
};
Base.prototype.baseMethod = function () {
return 'baseMethod';
};
Base.prototype.baseInitMethod = function () {
return 'baseInitMethod';
};
Base.prototype.basePrototypeMethod = function () {
return "basePrototypeMethod";
};
var Specific = function () {
Base.apply(this, arguments);
};
Specific.prototype.baseInitMethod = function () {
Base.prototype.baseInitMethod.apply(this,arguments);
};
Specific.prototype.specificMethod = function () {
return 'specificMethod';
};
Specific.prototype.specificInitMethod = function () {
var basePrototypeMethodCallResult = Base.prototype.basePrototypeMethod.apply(this,arguments);
};
You're overwriting the baseInitMethod of Base inside Specific, with Specific's definition, so why would you ever want to call the Base version? If you simply remove the overwrite of the function you should call the Base definition:
var Base = function() {
this.baseMethod = function(){
return 'baseMethod';
};
this.baseInitMethod = function() {
return 'baseInitMethod';
}
}
Base.prototype.basePrototypeMethod = function() {
return "basePrototypeMethod";
};
var Specific = function() {
Base.call(this);
this.baseInitMethod(); // calls the Base definition only
this.specificMethod = function(){
return 'specificMethod';
}
this.specificInitMethod = function() {
return this.basePrototypeMethod();
}
}
One might argue "Why always trying to mimic 'classical' behaviour and fuss with call and apply instead of embracing the prototype delegation pattern instead?"
Here is what I would code :
var Base = {
baseVariable1: "baseValue1",
baseVariable2: "baseValue2",
baseMethod: function () {
return 'baseMethod';
},
baseInitMethod: function () {
return 'baseInitMethod';
}
}
var Specific = Object.create(Base);
Specific.variable1 = "value1";
Specific.variable2 = "value2";
Specific.specificInitMethod = function () {
return 'specificInitMethod' + '-' + this.baseInitMethod();
}
Specific.specificMethod = function () {
return 'specificMethod' + '-' + this.baseInitMethod();
}
var s = Object.create(Specific);
console.log(s.baseInitMethod());
console.log(s.baseVariable1);
console.log(s.baseVariable2);
console.log(s.variable1);
console.log(s.variable2);
console.log(s.baseMethod());
console.log(s.specificInitMethod());
console.log(s.specificMethod());
class Parentable {
get parent() {
return this.__proto__.__proto__;
}
}
class A extends Parentable {
say() {
console.log('Hello from A');
}
}
class B extends A {
say() {
console.log('Im not A, I am B! But A send you a message:');
this.parent.say();
}
}
(new B()).say();
How could I do this?
Class
var Factory = (function() {
var Class = function() {
this.name = 'John';
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
Usage
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
this.name // => returns undenfined
});
Thanks for any help!
You need to save a reference to this in the outer Class function and call call:
var instance = this;
this.methods = {
get: function(callback) {
callback.call(instance);
}
};
var Class = function() {
// Save a reference to this that can be used in local closures.
var me = this;
this.name = 'John';
this.methods = {
get: function(callback) {
// Use 'call()', passing the reference to the 'Class' object
callback.call(me);
}
};
};
#SLaks - The declaration of scope as a Global variable is bad practice.
#Ferdinand Beyer - have you tested if it functions?
The better way will be the scope binding. The Prototype javascript framework produced a nice concept and we can easily implement it like
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}
and then yoou code should have only a single change and it will maintin the scope of your class.
var Factory = (function() {
var Class = function() {
this.name = 'John';
var me = this;
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
console.info(this.name) // => returns undenfined
}.bind(MyClass));
I mean only the function call get with .bind(MyClass)