Patch 'this' variable with jQuery - javascript

How do you think, is it ok to rewrite this variable in constructor with patched one with jquery? Then you will have some helpful methods for handling events, etc. What advantages, disadvantages it has?
Some example:
var Transformer = function(name, rase) {
this = $(this); // patch `this` with jQuery
this.name = name;
this.rase = rase;
}
Transformer.prototype.transform = function() {
// now we can do that
this.trigger('transformstart');
}
Is this a bad practice?
UPD
It's just impossible, you'll have an error:
ReferenceError: "Invalid left-hand side in assignment"

I find helpful to have $this field.
var Transformer = function(name, rase) {
this.$this = $(this);
this.name = name;
this.rase = rase;
}
Transformer.prototype.transform = function() {
this.$this.trigger('transformstart');
}

If you only need a jQuery as a events helper, you can make an "events" property:
var Transformer = function(name, rase) {
this.events = $({});
// other code
}
Transformer.prototype.transform = function() {
this.events.trigger('transformstart');
}
// public usage
var optimus = new Transformer('Optimus', 'Autobots');
optimus.events.on('transformstart', function() {
console.log('say hello to my gun!');
});

Related

Private prototype methods that can share scope and access the instance

I'm looking for a pattern that both allows me to create a private scope that my function prototype has access to and I need to be able to access the instance from within that scope.
For example, this is how I am currently achieving "private methods" (disregard what the code actually does, just look at the structure.)
function InfoPreview() {
this.element = document.createElement('div');
}
//Private Methods
InfoPreview.prototype.__newLine = function () {
this.element.appendChild(createElement({tagName:'br'}));
};
InfoPreview.prototype.__padLeft = function(level) {
var padding = createElement({tagName: 'span'});
this.element.appendChild(padding);
$(padding).width(level * 10);
};
InfoPreview.prototype.__print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
this.element.appendChild(span);
this.element.style["margin-right"]='10px';
};
InfoPreview.prototype.__puts = function(string) {
this.__print(string);
this.__newLine();
};
//Public Methods
InfoPreview.prototype.update = function(info) {
$(this.element).empty();
for (var record in info) {
this.__puts(record);
}
};
Notice that I am not creating private methods at all, just utilizing a naming convention. Additionally notice that I have no way to cache chain-lookups, such as this.element.
I would like to create a private scope by utilizing a revealing module pattern, like this:
InfoPreview.prototype = (function() {
var self = this, //<- `this` is actually the global object now.
el = self.element;
var newLine = function () {
el.appendChild(createElement({tagName:'br'}));
};
var padLeft = function(level) {
var padding = createElement({tagName: 'span'});
el.appendChild(padding);
$(padding).width(level * 10);
};
var print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
el.appendChild(span);
el.style["margin-right"]='10px';
};
var puts = function(string) {
print(string);
newLine();
};
var update = function(info) {
$(el).empty();
for (var record in info) {
puts(record);
}
};
return {
update: update
};
})();
The above approach doesn't work however, because the value of this within the IIFE is the global object, not the instance. I need a way to access the instance.
Is there any downside of using a constructor pattern?
function Foo(constructorArg) {
/* private variables */
var privVar = 'I am private',
cArg = constructorArg;
/* public variables */
this.pubVar = 'I am public';
/* private function */
function privFunc() {
return 'I am a private function';
}
/* public function */
this.publicFunc = function() {
return 'I am a public function and I call privVar->"' + privVar + '" and privFunc->"' + privFunc() + '"';
}
}
var foo = new Foo('something');
console.log('foo.pubVar', foo.pubVar); //ok
console.log('foo.publicFunc()', foo.publicFunc()); // ok
console.log('foo.privVar', foo.privVar); // undefined
console.log('foo.privFunc', foo.privFunc()); //error
Why you should use it (as requested in comments):
Simply put, because it is the only (sane) way of creating a "true private scope", which was your question.
The alternative is using a convention which tell developers what properties and methods are private, usually by prefixing them with an underscore _, which you already implemented but disliked.
Note that constructor and prototype are different things and enable you to do different stuff. Nothing prevents you from mixing both up.
Memory usage
Regarding memory usage, in modern js engines, such as Google's V8 JavaScript Engine, the constructor pattern might actually be faster.
V8 has hidden types created internally for objects at runtime; objects with the same hidden class can then use the same optimized generated code.
For example:
function Point(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// At this point, p1 and p2 have a shared hidden class
p2.z = 55;
// warning! p1 and p2 now have different hidden classes!
Prototype chaining always require two lookups, so it might even be a tiny inny LITTLE bit slower. Note: Can't back up on this, jsperf.com is down!
Constructor pattern is dirty (sic)
Performance was my reason. I hadn't realized that. However it still feels dirty to me
I don't know why you feel the constructor pattern is dirty. Maybe it's because it has some "specifics", limitations and potential pitfalls you should be aware
this can mean different things
It's easy to forget the new keyword causing weird and hard to debug bugs due to shared state
You can't easily split your object across multiple files (without resorting to a build tool or some 3rd party injector)
However, 1 and 2 are also true for prototype declaration style so...
if you feel this is not adequate, you might want to look at the module pattern.
Within each function, you will have access to the this value you want.
var Example = function() {};
Example.prototype = (function() {
var privateUpdate = function() {
document.getElementById('answer').innerHTML = this.foo;
}
return {
update: privateUpdate
}
})();
var e = new Example();
e.foo = 'bar';
e.update();
<div id="answer"></div>
As a variant on what Pointy is suggesting, you can try this pattern;
infoPreview.prototype = (function() {
var self = null;
var update = function(info) {
....
};
var firstUpdate = function(info) {
self = this;
functions.update = update;
update(info);
}
var functions = {
update: firstUpdate
};
return functions;
})();
Maybe something like that, without prototyping :
https://jsfiddle.net/ynwun1xb
var Fn = function(el) {
this.el = el;
var myMethod = function() {
console.log('do something in method with element', this.el);
}.bind(this);
return {
myPublicMethod: function() {
return myMethod();
}
}
}
var instancedFn = new Fn('first instance element')
.myPublicMethod()
;
var instancedFn2 = new Fn('second instance element')
.myPublicMethod()
;

RequireJS, Circular Dependencies and Exports "Magic" Method

I've been trying to get RequireJS set up to handle circular dependencies using the special 'exports' magic module as recommended by James Burke's answer to this question.
Following the example given by #jrburke in that question:
define("Employee", ["exports", "Company"], function(Company) {
function Employee(name) {
this.name = name;
this.company = new Company.Company(name + "'s own company");
};
exports.Employee = Employee;
});
define("Company", ["exports", "Employee"], function(Employee) {
function Company(name) {
this.name = name;
this.employees = [];
};
Company.prototype.addEmployee = function(name) {
var employee = new Employee.Employee(name);
this.employees.push(employee);
employee.company = this;
};
exports.Company = Company;
});
jsfiddle
The problem is that using his own example, the exports module is undefined, and therefore exports.Employee and exports.Company don't set. If I try to include exports as an argument of the define callback functions, it simply initializes in both cases as empty and does not carry the constructor functions it was assigned.
What am I doing wrong?
EDIT: Through trial and error, I got the above code working at: http://jsfiddle.net/jpk45vow/4/. Can anyone explain why it works, because it makes no sense to me.
Edit: I couldn't find more info about the magic exports method. I could, however, mimic its intended behavior with a dummy "Container" module. See it in this fiddle: http://jsfiddle.net/amenadiel/a7thxz98/
console.log("start");
define("Container",function() {
var Container={};
return Container;
});
define("Employee", ["Container"], function(Container) {
var Employee= function(name) {
this.name = name;
this.company = new Container.Company(name + "'s own company");
};
Container.Employee = Employee;
});
define("Company", ["Container"], function(Container) {
var Company=function(name) {
this.name = name;
this.employees = [];
};
Company.prototype.addEmployee = function(name) {
var employee = new Container.Employee(name);
this.employees.push(employee);
employee.company = this;
};
Container.Company = Company;
});
define("main", ["Container","Employee","Company" ], function ( Container) {
var john = new Container.Employee("John");
var bigCorp = new Container.Company("Big Corp");
bigCorp.addEmployee("Mary");
console.log(bigCorp);
});
require(["main"]);

How to get Javascript class fields and functions

Is there any way to get functions and fields from JavaScript class without initializing an object of that class?
var SimpleClass = function() {
this.type = 'singleClassType';
this.getType = function() {
var self = this;
return self.type;
}
}
I want to get type field (which is like static).
I can do something like this, but I really don`t want to use prototype of class:
SimpleClass.prototype.type = 'customName'
Here is the code I use:
var Class1 = function(id) {
this.id = id;
}
Class1.prototype.type = 'class1';
var Class2 = function(id) {
this.id = id;
}
Class2.prototype.type = 'class2';
var Class3 = function(id) {
this.id = id;
}
Class3.prototype.type = 'class3';
var Class4 = function(id) {
this.id = id;
}
Class4.prototype.type = 'class4';
var xml = {},
xmlText = '';
$(document).ready(function(){
generateObjects();
});
function generateObjects() {
for(var i=1;i<5;i++){
if(typeof eval('Class'+i).prototype.getHtml === 'undefined'){
$.ajax({
dataType: 'xml',
url: 'file.xml',
async: false,
success: function(data){
xmlText = data;
addClassData();
}
});
function addClassData(){
xml['"'+eval('Class'+i).prototype.type+'"'] = xmlText;
}
eval('Class'+i).prototype.getHtml = function(){
var self = this;
return xml['"'+self.type+'"'];
}
}
var kl = eval('Class'+i),
obj = new kl(i);
console.log(obj.getHtml());
}
}
Is there any way to get functions and fields from JavaScript class without initializing an object of that class?
No. Unless you decompile the function, parse the JS code and look for property assignments.
I can do something like this, but I really don't want to use prototype of class:
There's nothing wrong with using the prototype if this field is supposed to be shared amongst all instances of the class.
If by "static" you mean that it's rather a class member than an instance member, you can put properties directly on the constructor as well:
var SimpleClass = function() {
this.getType = function() {
return SimpleClass.type;
// alternatively, something like `this.constructor.type`
// but only if you understand when this works and when not
}
}
SimpleClass.type = 'singleClassType';
Accessing the property/field like this:
var SimpleClass = function(){
this.type = 'singleClassType';
this.getType = function(){
var self = this;
return self.type;
}
}
SimpleClass["type"] = 'customName';
alert(SimpleClass["type"]);
should work too. Have a look at this MDN article - property accessors.
Have a look at this MDN article - Working with objects for more thorough information about OOP concepts using JavaScript in order to avoid the problem that #PaulS pointed out in his comment.

Javascript module pattern, nested functions, and sub modules

I am trying to wrap my head around javascript modules, but I'm unsure how to split up a module into further sub modules. I have read that nested functions are not really a great idea, due to performance, so how do I break up a function in a module? For example, lets say I have the following module:
var Editor = {};
Editor.build = (function () {
var x = 100;
return {
bigFunction: function () {
// This is where I need to define a couple smaller functions
// should I create a new module for bigFunction? If so, should it be nested in Editor.build somehow?
}
};
})();
bigFunction is only related to Editor.build. Should I attach the smaller functions that make up bigFunction to the prototype bigFunction object? I'm not even sure if that would make sense.
var Editor = {};
Editor.build = (function () {
var x = 100;
return {
bigFunction: function () {
bigFunction.smallFunction();
bigFunction.prototype.smallFunction = function(){ /*do something */ };
// not sure if this even makes sense
}
};
})();
Can someone please throw me in the right direction here? There is so much misleading information online, and would just like a definite guide on how to deal with this sort of modularization.
Thank you.
Here is a snippet I use to make names for an input:
var dynamicCounter = 0;
//custom dropdown names
var createContainerNames = function () {
function Names() {
this.id = "Tasks_" + dynamicCounter + "__ContainerId";
this.name = "Tasks[" + dynamicCounter + "].ContainerId";
this.parent = "task" + dynamicCounter + "Container";
}
Names.prototype = { constructor: Names };
return function () { return new Names(); };
} ();
And then I use it:
var createdNames = createContainerNames();
var createdId = createdNames.id;
dynamicCounter++;
var differentNames = createContainerNames();
var differentId = differentNames.id;
Another approach would be to do this:
var NameModule = function(){
//"private" namemodule variables
var priv1 = "Hello";
//"private namemodule methods
function privMethod1(){
//TODO: implement
}
//"public namemodule variables
var pub1 = "Welcome";
//"public" namemodule methods
function PubMethod(){
//TODO: pub
}
return {
pub1 : pub1,
PubMethod: PubMethod
};
and then to use it
var myPubMethod = new NameModule();
myPubMethod.PubMethod();
var pubVar = myPubMethod.pub1;
EDIT
You could also take this approach:
var mod = function(){
this.modArray = [];
};
mod.prototype = {
//private variables
modId: null,
//public method
AddToArray: function (obj) {
this.modArray.push(obj);
}
}

Calling method using JavaScript prototype

Is it possible to call the base method from a prototype method in JavaScript if it's been overridden?
MyClass = function(name){
this.name = name;
this.do = function() {
//do somthing
}
};
MyClass.prototype.do = function() {
if (this.name === 'something') {
//do something new
} else {
//CALL BASE METHOD
}
};
I did not understand what exactly you're trying to do, but normally implementing object-specific behaviour is done along these lines:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.doStuff = function() {
// generic behaviour
}
var myObj = new MyClass('foo');
var myObjSpecial = new MyClass('bar');
myObjSpecial.doStuff = function() {
// do specialised stuff
// how to call the generic implementation:
MyClass.prototype.doStuff.call(this /*, args...*/);
}
Well one way to do it would be saving the base method and then calling it from the overriden method, like so
MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){
if (this.name === 'something'){
//do something new
}else{
return this._do_base();
}
};
I'm afraid your example does not work the way you think. This part:
this.do = function(){ /*do something*/ };
overwrites the definition of
MyClass.prototype.do = function(){ /*do something else*/ };
Since the newly created object already has a "do" property, it does not look up the prototypal chain.
The classical form of inheritance in Javascript is awkard, and hard to grasp. I would suggest using Douglas Crockfords simple inheritance pattern instead. Like this:
function my_class(name) {
return {
name: name,
do: function () { /* do something */ }
};
}
function my_child(name) {
var me = my_class(name);
var base_do = me.do;
me.do = function () {
if (this.name === 'something'){
//do something new
} else {
base_do.call(me);
}
}
return me;
}
var o = my_child("something");
o.do(); // does something new
var u = my_child("something else");
u.do(); // uses base function
In my opinion a much clearer way of handling objects, constructors and inheritance in javascript. You can read more in Crockfords Javascript: The good parts.
I know this post is from 4 years ago, but because of my C# background I was looking for a way to call the base class without having to specify the class name but rather obtain it by a property on the subclass. So my only change to Christoph's answer would be
From this:
MyClass.prototype.doStuff.call(this /*, args...*/);
To this:
this.constructor.prototype.doStuff.call(this /*, args...*/);
if you define a function like this (using OOP)
function Person(){};
Person.prototype.say = function(message){
console.log(message);
}
there is two ways to call a prototype function: 1) make an instance and call the object function:
var person = new Person();
person.say('hello!');
and the other way is... 2) is calling the function directly from the prototype:
Person.prototype.say('hello there!');
This solution uses Object.getPrototypeOf
TestA is super that has getName
TestB is a child that overrides getName but, also has
getBothNames that calls the super version of getName as well as the child version
function TestA() {
this.count = 1;
}
TestA.prototype.constructor = TestA;
TestA.prototype.getName = function ta_gn() {
this.count = 2;
return ' TestA.prototype.getName is called **';
};
function TestB() {
this.idx = 30;
this.count = 10;
}
TestB.prototype = new TestA();
TestB.prototype.constructor = TestB;
TestB.prototype.getName = function tb_gn() {
return ' TestB.prototype.getName is called ** ';
};
TestB.prototype.getBothNames = function tb_gbn() {
return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this);
};
var tb = new TestB();
console.log(tb.getBothNames());
function NewClass() {
var self = this;
BaseClass.call(self); // Set base class
var baseModify = self.modify; // Get base function
self.modify = function () {
// Override code here
baseModify();
};
}
An alternative :
// shape
var shape = function(type){
this.type = type;
}
shape.prototype.display = function(){
console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){
// call implementation of the super class
this.__proto__.display.apply(this,arguments);
}
If I understand correctly, you want Base functionality to always be performed, while a piece of it should be left to implementations.
You might get helped by the 'template method' design pattern.
Base = function() {}
Base.prototype.do = function() {
// .. prologue code
this.impldo();
// epilogue code
}
// note: no impldo implementation for Base!
derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }
If you know your super class by name, you can do something like this:
function Base() {
}
Base.prototype.foo = function() {
console.log('called foo in Base');
}
function Sub() {
}
Sub.prototype = new Base();
Sub.prototype.foo = function() {
console.log('called foo in Sub');
Base.prototype.foo.call(this);
}
var base = new Base();
base.foo();
var sub = new Sub();
sub.foo();
This will print
called foo in Base
called foo in Sub
called foo in Base
as expected.
Another way with ES5 is to explicitely traverse the prototype chain using Object.getPrototypeOf(this)
const speaker = {
speak: () => console.log('the speaker has spoken')
}
const announcingSpeaker = Object.create(speaker, {
speak: {
value: function() {
console.log('Attention please!')
Object.getPrototypeOf(this).speak()
}
}
})
announcingSpeaker.speak()
No, you would need to give the do function in the constructor and the do function in the prototype different names.
In addition, if you want to override all instances and not just that one special instance, this one might help.
function MyClass() {}
MyClass.prototype.myMethod = function() {
alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
MyClass.prototype.myMethod_original.call( this );
alert( "doing override");
};
myObj = new MyClass();
myObj.myMethod();
result:
doing original
doing override
function MyClass() {}
MyClass.prototype.myMethod = function() {
alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
MyClass.prototype.myMethod_original.call( this );
alert( "doing override");
};
myObj = new MyClass();
myObj.myMethod();

Categories

Resources