JavaScript prototype(ing) question - javascript

Trying to grasp Prototyping in Javascript. Trying to create my own namespace to extend the String object in JavaScript.
Here is what I have so far (a snippet):
var ns {
alert: function() {
alert (this);
}
}
String.prototype.$ns = ns;
As you can see, I am trying to place what will be a series of functions into the ns namespace. So I can execute a command like this:
"hello world".$ns.alert();
But the problem is, the this doesn't reference the text being sent (in this case, "hello world"). What I get is an alert box with the following:
[object Object]
Not having a full grasp of the object-oriented nature of JavaScript, I am at a loss, but I am guessing I am missing something simple.
Does anyone know how to achieve this (get the source text from the nested object)? Short of that, I am left with having to do procedural programming ( ns.alert("hello world"); ) which I am trying to avoid.
Thanks -

This is happening because when you invoke a reference, its base object is set as the this value of the invoked method (more technical details here).
So when you invoke "hello world".$ns.alert(); the this value inside your alert method, will refer to "hello world".$ns, which is String.prototype.$ns.
I don't think adding object levels (namespaces) inside the prototype of built-in objects can be useful, I usually recommend to not modify objects you don't own.

Related

Can I make a variable of a class into a function with JavaScript? [duplicate]

Is it possible to make an object callable by implementing either call or apply on it, or in some other way? E.g.:
var obj = {};
obj.call = function (context, arg1, arg2, ...) {
...
};
...
obj (a, b);
No, but you can add properties onto a function, e.g.
function foo(){}
foo.myProperty = "whatever";
EDIT: to "make" an object callable, you'll still have to do the above, but it might look something like:
// Augments func with object's properties
function makeCallable(object, func){
for(var prop in object){
if(object.hasOwnProperty(prop)){
func[prop] = object[prop];
}
}
}
And then you'd just use the "func" function instead of the object. Really all this method does is copy properties between two objects, but...it might help you.
ES6 has better solution for this now. If you create your objects in a different way (using class, extending 'Function' type), you can have a callable instance of it.
See also: How to extend Function with ES6 classes?
Following the same line of #Max, but using ES6 extensions to Object to pass all properties and prototype of an object obj to the callable func.
Object.assign(func, obj);
Object.setPrototypeOf(func, Object.getPrototypeOf(obj));
Others have provided the current answer ("no") and some workarounds. As far as first-class support in the future, I suggested this very thing to the es-discuss mailing list. The idea did not get very far that time around, but perhaps some additional interest would help get the idea moving again.
https://esdiscuss.org/topic/proposal-default-object-method
"CALLABLE OBJECTS"
I haven't seen mention of this type of answer yet.. but this is how I do "callable" objects:
<< PSEUDO CODE >>
{...objectWithFunctionsInside}[keyString](optionalParams)
short example defining first, simplest and preferred method if I just want a "callable object," in my definition:
let obj = {
o:()=>{return("oranges")},
b:()=>{return("bananas")},
s:"something random here, doesn't have to be functions"
}
obj["o"]()
short example of nameless object being run within a function's return, with parameters (note parameters works in the first example too):
function autoRunMyObject(choice,param){
return{
o:(p)=>{return(p+"oranges")},
b:(p)=>{return(p+"bananas")},
}[choice](param)
}
autoRunMyObject("b","orange you glad I didn't say ")
and that's pretty much it
You could even get weirder with it and do nameless functions that auto-run themselves and produce an output right away... for no reason, lol.
... hit F12 and copy this code into your browser console and press enter, you'll get an output right away with the full string:
((autoparam="o")=>{return{
o:(p)=>p+"oranges",
b:(p)=>p+"bananas",
}[autoparam]("I guess this time it's ")})()
You could even pass in the string of "b" in the final parenthesis for a different output from the default "o".
Also, each of my examples (minus the pseudo code first example) are easily copy/paste-able into the browser console for quick testing -- it's a nice place to experiment with JS.
In summary -- this is how I like to do "callable objects"
It's much better than
SWITCH(){CASE:BREAK;};
statements and
IF{}ELSE IF(){}ELSE IF(){};
chains.

Functions as object in Javascript

Hey guys I'm kind of new to JS and found out that functions are also objects.
This means I can add properties to them like this:
let func = function(){};
func.foo = "foo";
console.log(func.foo); // prints foo
However when we now do this:
console.log(func);
It will return (using chrome):
Why does it not show the properties of the object like it usually shows on other type of objects?
Also when we for instance try to console.log(Function) it will return the following output:
What is this native code? What I got from other sources was that it is code written in another programming language(C, C++) that programmed the functionality of this constructor.
Thanks in advance!
Chrome’s console displays functions’ bodies instead of their properties, because that’s usually more useful. It’s much easier to tell when you don’t use an empty function:
And it’ll indeed substitute in [native code] when there is no JavaScript body to be shown.
As #ibrahim mahrir points out, you can use console.dir(func) to get both the default inspection and an expandable list of properties.

this in javascript not populating data as expected

My code -
<script type="application/javascript">
var firstObject = {
sayHello : function(){
document.write("My name is "+ this.myName +"<br>");
},
myName : "Swapnesh Sinha"
};
var secondObject = {myName : "Sanjay Sinha"};
document.write("First one " + firstObject.sayHello() );
document.write("<br>");
document.write("Second one "+ secondObject.myName);
</script>
Source - http://learn.jquery.com/javascript-101/this-keyword/
Expecting output -
First one Swapnesh Sinha
Second one Sanjay Sinha
Unexpected Output (from my sense)-
My name is Swapnesh Sinha
First one undefined
Second one Sanjay Sinha
Let me know the case why it returns undefined however source is mentioning to return name ? or something I am getting wrong from my side
In your first document.write, you call a function, and ask the return value of the function to be concatenated to the string "First one ".
The function is evaluated, at which point "My name is Swapnesh Sinha" gets outputed via document.write call inside the object. That function call however does not return a value, hence it is undefined, and that gets concatenated to "First one", which is then printed.
Here is the working fiddle: JsFIDDLE
Here is what you fail to understand, as most jQuery developers: JavaScript scoping.
Basically, in order for a property to be accessed via this, it has to be nested in the Object.prototype.
Correction
When you define the object properties inline, calling this will still point to the right object. However, the pattern I gave you, even though less popular, is a much neater and better approach.
The prototype is the JavaScript way of OOP. If you are looking for solid OOP style JS and for proper definition of models, improved code maintainability and better coding style, it is preferred to define classes using the pattern I gave you, as it will allow you to make a strong distinction between static functions and classes. It is also the natural flow of JavaScript, where everything is an object.
In high level JavaScript programming(powerful Ajax applications or applications where for one reason or the other the browser has to perform more advanced computation), the below style is always preferred. Static functions placed under a namespace are still defined separately:
var namespace = {};
namespace.firstStaticFunc = function() {/*do stuff etc;*/};
namespace.secondStaticFunc = function() { return !1; };
The only reason why you use your definition pattern is enums and hash maps. For instance:
var typesOfChicken = {
RED: 'red',
BLUE: 'blue'
};
The above is always used for things like internationalization and avoidance of hard coded values. Also, it helps JS minifiers to a better job. Given the above, you can say:
console.log(typesOfChicken.RED);// will print red.
console.log("red");// wil still print red
But, when I want to change red to something else, using enums I only have to do a single change. Also, the minifier can replace typesOfChicken.RED with a.b, whereas "RED" will always be "RED". It's unminifiable.
var firstObject = function() { };
firstObject.prototype.myName = "Swapnesh Sinha";//this will not be nested as an instance property.
firstObject.prototype.sayHello = function() {
alert(this.myName);// will now correctly display Swapnesh Sinha
};
// to use your first object.
var instance = new firstObject();
instance.sayHello();
To properly make use of scope, use the pattern I gave you, which is an Object Oriented pattern and the right approach to defining classes in JS.
And now you have a great way to organize your JavaScript code, it's fair easier to maintain, scope is a lot more obvious and most important of all you can immediately make a distinction between static functions and classes.
replace document.write() with return in your sayHello function

Javascript Object Prototype

I was reading Prototypes in javascript and I have written 2 small js codes which are outputting exactly same. I just want to know what is the difference between them:
Code 1:
String.sam = function() { alert('fine') };
'ok'.sam();
Code 2 with prototype:
String.prototype.sam = function() { alert('fine') };
'ok'.sam();
Please clarify the difference and the better way to use the code.
Thanks
Your first example doesn't work. What you are doing is creating a static method on the string object so you would have to call it statically
//OK
String.sam();
//not OK, raises error
'hello'.sam();
In your second example the keyword this will refer to the instance of the string you call it on. So you can do something like
String.prototype.sam = function() {
console.log( this.toUpperCase() );
}
'hello'.sam(); // HELLO
This technique, although powerful is frowned upon in certain quarters. It is known as Guerrilla patching, Monkey punching or similar things.
There are a few reasons it is considered bad:
Hard to debug (you've changed the language)
Easy to break other code on the page that is not aware you've altered a prototype
Possible clashes with future enhancements of the core.
Probably lots more
I think, your first method adds only for this special property the alert() method. If you want create another instance, you have to do the same thing again. With protoype you define it more generally so you don't have to do the same thing again for another instance.
Perhaps http://www.javascriptkit.com/javatutors/proto.shtml will help you to understand it better.

Javascript object encapsulation that tracks changes

Is it possible to create an object container where changes can be tracked
Said object is a complex nested object of data. (compliant with JSON).
The wrapper allows you to get the object, and save changes, without specifically stating what the changes are
Does there exist a design pattern for this kind of encapsulation
Deep cloning is not an option since I'm trying to write a wrapper like this to avoid doing just that.
The solution of serialization should only be considered if there are no other solutions.
An example of use would be
var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());
A jsfiddle snippet might help : http://jsfiddle.net/Raynos/kzKEp/
It seems like implementing an internal hash to keep track of changes is the best option.
[Edit]
To clarify this is actaully done on node.js on the server. The only thing that changes is that the solution can be specific to the V8 implementation.
Stripping away the javascript aspect of this problem, there are only three ways to know if something has changed:
Keep a copy or representation to compare with.
Observe the change itself happening in-transit.
Be notified of the change.
Now take these concepts back to javascript, and you have the following patterns:
Copy: either a deep clone, full serialization, or a hash.
Observe: force the use of a setter, or tap into the javascript engine (not very applicable)
Notify: modifying the code that makes the changes to publish events (again, not very applicable).
Seeing as you've ruled out a deep clone and the use of setters, I think your only option is some form of serialisation... see a hash implementation here.
You'll have to wrap all your nested objects with a class that reports you when something changes. The thing is, if you put an observer only in the first level object, you'll only receive notifications for the properties contained in this object.
For example, imagine you have this object:
var obj = new WrappedObject({
property1: {
property1a: "foo",
property1b: 20,
}
})
If you don't wrap the object contained in porperty1, you'll only receive a "get" event for property1, and just that, because when someone runs obj.property1.property1a = "bar" the only interaction that you'll have with obj, will be when it asks for the reference of the object contained in property1, and the modification will happen in an unobserved object.
The best approach I can imagine, is iterating over all the properties when you wrap the first object, and constructing recursively a wrapper object for every typeOf(property) == "Object".
I hope my understanding of your question was right. Sorry if not! It's my first answer here :$.
There's something called reactive programming that kind of resembles what you ask about, but its more involved and would probably be overkill.
It seems like you would like to keep a history of values, correct? This shouldn't be too hard as long as you restrit changes to a setter function. Of course, this is more difficult in javascript than it is in some other languages. Real private fields demand some clever use of closures.
Assuming you can do all of that, just write something like this into the setter.
function setVal(x)
{
history.push(value);
value = x;
}
You can use the solution that processing.js uses.
Write the script that accesses the wrapped object normally...
var foo = state.get();
foo.bar = "baz";
state.update();
client.tell(state.recentChange());
...but in the browser (or on the server if loading speed is important) before it runs, parse the code and convert it to this,
var foo = state.get();
state.set(foo, "bar", "baz");
state.update();
client.tell(state.recentChange());
This could also be used to do other useful things, like operator overloading:
// Before conversion
var a=new Vector(), b=new Vector();
return a + b * 3;
// After conversion
var a=new Vector(), b=new Vector();
return Vector.add(a,Vector.multiply(b,3));
It would appear that node-proxy implements a way of doing this by wrapping a proxy around the entire object. I'll look into more detail as to how it works.
https://github.com/samshull/node-proxy

Categories

Resources