Manipulating the JS prototype - javascript

I want to add a $error element to all my objects including "primitive" objects such as string and number.
I have the following codepen which just adds this value (via a function) to the Object class.
http://codepen.io/anon/pen/nglbL
For convenience, here is the code:-
Object.prototype.setError = function (str) {
this.$error = str;
this.$errorObj = { };
console.log("value of object is " + this.toString());
console.log("Setting error to " + this.$error);
};
Object.prototype.getError = function() {
console.log("error is " + this.$error);
console.log("error object is " + this.$errorObj);
return this.$error;
}
var obj = {
"str" : "string me!",
"bool" : true,
"int" : 1
}
obj.str.setError("error");
console.log("Retriving error and it is " + obj.str.getError());
Clearly, I don't understand how the prototypical inheritance works.
Thanks.

In JavaScript primitives are wrapped in background by its Object counterparts, these objects are called "Wrapper Objects", every time you treat a primitive as an object, a new wrapper object is created. This process occurs transparently, and a variable holding a string primitive doesn't hold a reference to an object, but the literal string value.
Wrapper objects won't survive for multiple uses! So, just don't try to define properties for strings, booleans and numbers, this simply doesn't work.
var a = {}; //this is a common object
a.test = "abc";
console.log(a.test);//will print "abc"
var b = "zzzz"; //declaring a string primitive
b.test = "abc"; //trying to add a property to this string, we're treating our primitive as an object
console.log(b.test);//will print undefined

Related

Checking if an object exists via .length

JSFiddle: https://jsfiddle.net/pd08dgxu/1/
I need to check whether a JavaScript object is empty or not. Suppose, in this fiddle, Obj1 is not empty (it contains the fields below) but Obj2 is {}.
In both cases, when I check obj1.length or obj2.length, I get Undefined (see alert). Shouldn't we check for existence by using the .length operator on all variables, whether strings or complex objects?
function getObject() {
return { 'color' : 'red',
'title' : 'my title'
};
}
var myObj1 = getObject();
var myObj2 = {}; //empty object
alert('myObj1 Length = ' + myObj1.length + ' myObj2 Length = ' + myObj2.length);
You cannot check the object's existance using obj.length.
You have to count the number of keys.
Try Object.keys(Obj).length
function getObject() {
return { 'color' : 'red',
'title' : 'my title'
};
}
var myObj1 = getObject();
var myObj2 = {}; //empty object
console.log('myObj1 Length = ' + Object.keys(myObj1).length + ' myObj2 Length = ' + Object.keys(myObj2).length);
The length property only works like that on Arrays.
To get the number of properties on any object, you can use the Object.keys method, which returns an array of all the property-names on an object. Like this: Object.keys(Obj).length.
isEnum
Here is my conventional JavaScript singleton which is a part of all my util. libs.
function isEnum(x){for(var i in x)return!0;return!1};
And it's faster than Object.keys in any aspect. Will work correctly in case you've accidentally dropped an Array in its argument instead of an Object.
It's use is exactly what you need it for to check if the object is empty or enumerable before deciding to iterate it or not.

How to set/update the value of a String object in JavaScript

I have an object with some properties which are String objects:
var obj = {
foo: new String("bar")
};
I am using String objects because I am needing to store additional sub-properties on the object while still being able to get the string value:
obj.foo.baz = "baz";
"" + obj.foo; //-> "bar";
I feel dumb for asking, but how can I update the value of a String object? Seems like some Array splice magic might need to be applied.
EDIT: Just to be clear, I understand string primitives in JS and immutability therein. This is an object I'm talking about. Here is the test that needs to pass:
assert.equal("" + obj.foo, "foo"); //-> true
assert.equal(obj.foo.baz, "baz"); //-> true
extend(obj, { foo: "foooooo" });
assert.equal("" + obj.foo, "foooooo"); //-> true
assert.equal(obj.foo.baz, "baz"); //-> true
You can't. Strings are immutable, regardless of how you "construct" them (literal or object).
What you should be doing is simply use an actual object to hold your values and your string.
At the most basic level this would be:
var obj = {
foo: "bar"
};
// later...
obj.baz = "baz";
"" + obj.foo; //-> "bar";
You can also consider using a monadic type as an "amplifier" / decorator, but that seems way overkill for this use case.
As a side note, adding properties and "random" functions to a string object is not a good OOP choice. These are strictly not relevant to the value that is the string, and only make sense to a higher level object, which is where they should reside.
You'd need to create a new String object and extend any new properties and values to that String object. I've provided a simple example below. That said, this example can be modified to suit your purposes (you'd create a custom extend or setter function).
Example of a property setter function
var createNewString = function (oldStringObj, string) {
var _new = new String(string);
var keys = Object.keys(oldStringObj); // returns only custom properties (not part of prototype)
for (var i=0,n=keys.length; i<n; i++){
var key = keys[i];
if (Number.isInteger(+key)) {
continue; // skip property if it's a numbered key
}
_new[key] = oldStringObj[key]; // simple assignment (not a deep copy) -- room for improvement
}
return _new;
};
Original object
var obj = {
foo: new String("bar")
};
obj.foo.baz = "baz"; // new property
Update the object
obj.foo = createNewString( obj.foo, 'foot' );
//obj.foo=='foot' and obj.foo.baz=='baz'
I suggest that you use a custom type for this, instead of the default String type. The ES6 spec defines that the underlying value for a String object is stored in its "[[StringData]] internal slot". The only place this slot is assigned is via the new String constructor, so it is implicitly immutable. You can create a new type which has the same string-like behaviours that you require, while being mutable.
class MutableString {
constructor(value) {
this.value = value;
}
toString() {
return this.value;
}
}
var obj = {
foo: new MutableString('bar')
};
obj.foo.baz = "baz";
console.assert("" + obj.foo == "bar");
console.assert(obj.foo + "" == "bar");
console.assert(obj.foo.baz == "baz");
console.assert(Object.keys({[obj.foo]: 1})[0] == "bar");
obj.foo.value = "foooooo";
console.assert("" + obj.foo == "foooooo");
console.assert(obj.foo + "" == "foooooo");
console.assert(obj.foo.baz == "baz");
console.assert(Object.keys({[obj.foo]: 1})[0] == "foooooo");
Because this isn't really a string it won't support any string methods, so it may not be suitable for your use. But it's more flexible and a little clearer, so I suggest considering it if possible.
It may be necessary to define a valueOf() method like toString() to handle some other cases, but I haven't verified.

Javascript - Store variable as object and function

I've seen instances of a variable being both an object and a string. Example:
alert(x + ""); // Hello
alert(x()); // World
This kind of thing is what jQuery does with the $ variable.
How might you get this effect?
No, a variable can't be both an object and a (primitive) string.
However, if you attempt to convert an object to a string (e.g. using obj + ''), the string returned by its toString method is used instead.
function x() {
return "World";
}
x.toString = function() {
return "Hello";
};

Is there any difference in creating string object [duplicate]

This question already has answers here:
What is the difference between string primitives and String objects in JavaScript?
(12 answers)
Closed 9 years ago.
What is the difference between creating a string object like this
var txt = new String("Hello World");
and this
var txt = "Heloo World";
First of all let's bust some myths. String literal is not a syntactic sugar.
> var txt = new String("Hello World");
> typeof x
"string"
> var txt2 = "Hello World";
> typeof txt2
"object"
As you can see these two things are of different type. Even more: one of them is object and the second is not. This has a practical consequence, like:
> new String("Hello World") == new String("Hello World")
false
> "Hello World" == "Hello World"
true
Another difference is that primitives are passed by value while objects by reference. This might save some memory if you are passing around lots of big strings. However both objects and literals are immutable so it really isn't a big deal (why would you pass lots of big strings if you're not going to modify them?).
Also you can add attributes to objects while you can't add them to primitive types. But that's not 100% true. You can add an attribute to the prototype of a primitive. Note that both literals and objects have the same prototype:
> String.prototype.test = 11;
> var x = new String("x");
> x.test;
11
> var y = "x":
> y.test;
11
There's very little practical use for String objects as created by new String("foo"). The only advantage a String object has over a primitive string value is that as an object it can store properties:
var str = "foo";
str.prop = "bar";
alert(str.prop); // undefined
var str = new String("foo");
str.prop = "bar";
alert(str.prop); // "bar"
Hope this helps..
The String constructor function returns an object of type String. Usually, you want a literal string value, because strictly comparing an object to a literal will always return false.
One is a string primitive and the other is a String object.
The advantage of String object over string primitive is that it can store properties
var x = "foobar"
x.y = "hello"
console.log(x.hello) /* Undefinded*/
var z = new String("foobar")
z.y = "hello"
console.log(z.y) /* hello*/
typeof x = "string"
typeof z = object.
also
x==z //true
x===z // false
Nothing much but beware of this,
var s = new String('A');
var s1 = String('A');
var s2 = 'A';
console.log(s === 'A');//fasle -- since type is Object
console.log(s1 === 'A');//true
console.log(s2 === 'A');//true
var txt = "Heloo World";
here 'txt' is a primitive data type. It has no methods, it is nothing more than a pointer to a raw data memory reference, which explains the much faster random access speed.
var txt = new String("Hello World");
If you use new, you're explicitly stating that you want to create an instance of an Object. Therefore, new String is producing an Object wrapping the String primitive, which means any action on it involves an extra layer of work.
The first returns a String object, the second returns a string.
typeof txt; //object
typeof txt2; //string
While they may act similar, txt !== txt2
The primitive data types are:
String
Number
Boolean
If you using:
var txt = "Heloo World";
this is primitive type data type alert(typeof txt); will give you string type.
In JavaScript all variable can be of object type, for each primitive their is a Object type.
var txt = new String("Heloo World");
here typeof will give you object.
For difference see jsfiddle
var str="text";
alert(typeof str); //string
var str2="text";
alert(str === str2); //true
str = new String("text changed");
alert(typeof str); //object
var str2 = new String("text changed");
alert(str === str2); //false
Nothing, really. In the first example you call the constructor of class String and put as a parameter the body of the string, where as in the second example it is done automatically at the interpretation phase.
So basically the second is syntactic sugar, where as the first isn't.
There is no difference in the functionality.

Can I create a method in an object?

I saw this code before, but I don't know what the meaning:
var person1 = {
toLocaleString : function(){
return "Nikolaos";
},
toString : function(){
return "Nicholas";
}
}
var person2 = {
toLocaleString : function(){
return "bum";
},
toString : function(){
return "Greg";
}
}
var people = [person1, person2];
alert(people.toString());
alert(people.toLocaleString());
does the function create an object with the method of toLocaleString and toString??or...??
That code is doing three things:
Using object literal syntax to create object instances
Using anonymous function expressions to create functions and bind them to properties on the objects. (Functions are first-class objects in JavaScript, so you can keep references to them, pass the references around, etc.)
Specifically, it's overriding two standard functions that all JavaScript objects inherit from the Object prototype.
Let's break it down a bit.
1) Object literal notation:
var obj = {propName: propValue};
The { and } in this case denote an object literal. Within an object literal, you can write propName: propValue to assign propValue to the property with the name propName on the object. This is the same as:
var obj = {}; // Get an empty object
obj.propName = propValue; // Add a property to it
You can do multiple properties separated with commas. So for instance:
var obj = {
author: "Douglas Adams",
title: "The Hitchhiker's Guide to the Galaxy",
answer: 42
};
That creates an object with three properties, two with string values and one with a number value.
Note that the right-hand side are processed just like an assignment, and so can be anything that can appear on the right-hand side of an assignment statement:
var x = "bar";
var obj = {
three: 1 + 2,
fubar: "foo " + x
};
The property names can be put in quotes if you like:
var x = "bar";
var obj = {
"three": 1 + 2,
"fubar": "foo " + x
};
...which is handy for specifying properties that have the names of reserved tokens (like "if", or "return") or formerly-reserved tokens (like "class") where it would be a syntax error if they weren't in quotes.
2) Now let's look at function expressions:
var f = function() { /* your code here */ };
That's a function expression. It creates a new function and assigns a reference to it to the variable f. You can call it by calling f().
var f = function(name) {
alert("Hi " + name);
};
f("Fred"); // alerts "Hi Fred"
1 + 2) So putting it together with object literal notation:
var obj = {
foo: function(name) {
alert("Hi " + name);
}
};
obj.foo("Fred"); // alerts "Hi Fred"
(I don't like anonymous functions, I prefer my functions to have names, but that's another topic.)
3) And finally: As maerics pointed out, the specific functions that are being used in that code are toString and toLocaleString, both of which are standard functions of JavaScript objects. That means that those will override the standard version and so return the given values whenever the standard function would have been called.
The toString() and toLocaleString() methods are implemented for all JavaScript objects by the specification of the language. So arrays (such as the one stored in the "people" variable) seem to implement those methods by returning each of their elements' string or "locale string" value, respectively (at least, in the web browsers we are testing).
That is, the Array class toString and toLocaleString methods must be implemented with something like:
Array.prototype.toString = function() {
var a = [];
for (var i=0; i<this.length; i++) {
a[i] = this[i].toString(); // Note "toString".
}
return a.join(",");
}
Array.prototype.toLocaleString = function() {
var a = [];
for (var i=0; i<this.length; i++) {
a[i] = this[i].toLocaleString(); // Note "toLocaleString".
}
return a.join(",");
}

Categories