Assigning the same function to different variables - javascript

I was going through the WURFL.js source, I saw this towards the bottom of the page:
var logo=document.getElementById("hero"),heroText=document.getElementById("hero"), ...
Obviously, the variables, logo and heroText, are referring to the same thing. Isn't that an unnecessary overhead on the DOM parsing in JavaScript (since JavaScript has to look for the id hero each time)? Apparently, a more efficient one is:
var logo=document.getElementById("hero");
var heroText = logo;
In that case, heroText could be another object or could also be referring to the same object as logo. I don't know which because I don't know how the JavaScript interpreter works (I'm a C# person, a learner, though).
So my question is really this: (I'm assuming WURFL didn't make a mistake) how does JavaScript interpret the two lines? Thanks, in advance.

The difference would be (if it weren't returning a DOM element) that if you do
var getObj = function() { return {} };
var a = getObj();
var b = getObj();
a.test = 'hi';
console.log(b);
// Object {}
But if you do:
var getObj = function() { return {} };
var a = getObj();
var b = a;
a.test = 'hi';
console.log(b);
// Object {test: "hi"}
One results in two unique objects, the other in two references to the same object.
var a = document.getElementById('notify-container')
var b = document.getElementById('notify-container')
a.test = 'hi'
console.log(b.test);
//"hi"
So, in the instance you are showing, yes it is more efficient to do
var logo=document.getElementById("hero");
var heroText = logo;

There clearly seams to be a mistake. Because document.getElementById returns a 'live' representation of a node. That means that whenever that element changes, the variable that holds tha node ( logo, heroText ) is also changed; also, if you check those two variables for equality they will be the same.

Related

Possible to get a reference to the value (location) of a js object key? [duplicate]

I used C++ before and I realized that pointers were very helpful. Is there anything in javascript that acts like a pointer? Does javascript have pointers? I like to use pointers when I want to use something like:
var a = 1;
var b = "a";
document.getElementById(/* value pointed by b */).innerHTML="Pointers";
I know that this is an extremely simple example and I could just use a, but there are several more complex examples where I would find pointers very useful. Any ideas?
No, JS doesn't have pointers.
Objects are passed around by passing a copy of a reference. The programmer cannot access any C-like "value" representing the address of an object.
Within a function, one may change the contents of a passed object via that reference, but you cannot modify the reference that the caller had because your reference is only a copy:
var foo = {'bar': 1};
function tryToMungeReference(obj) {
obj = {'bar': 2}; // won't change caller's object
}
function mungeContents(obj) {
obj.bar = 2; // changes _contents_ of caller's object
}
tryToMungeReference(foo);
foo.bar === 1; // true - foo still references original object
mungeContents(foo);
foo.bar === 2; // true - object referenced by foo has been modified
You bet there are pointers in JavaScript; objects are pointers.
//this will make object1 point to the memory location that object2 is pointing at
object1 = object2;
//this will make object2 point to the memory location that object1 is pointing at
function myfunc(object2){}
myfunc(object1);
If a memory location is no longer pointed at, the data there will be lost.
Unlike in C, you can't see the actual address of the pointer nor the actual value of the pointer, you can only dereference it (get the value at the address it points to.)
I just did a bizarre thing that works out, too.
Instead of passing a pointer, pass a function that fills its argument into the target variable.
var myTarget;
class dial{
constructor(target){
this.target = target;
this.target(99);
}
}
var myDial = new dial((v)=>{myTarget = v;});
This may look a little wicked, but works just fine. In this example I created a generic dial, which can be assigned any target in form of this little function "(v)=>{target = v}". No idea how well it would do in terms of performance, but it acts beautifully.
due to the nature of JS that passes objects by value (if referenced object is changed completely) or by reference (if field of the referenced object is changed) it is not possible to completely replace a referenced object.
However, let's use what is available: replacing single fields of referenced objects. By doing that, the following function allows to achieve what you are asking for:
function replaceReferencedObj(refObj, newObj) {
let keysR = Object.keys(refObj);
let keysN = Object.keys(newObj);
for (let i = 0; i < keysR.length; i++) {
delete refObj[keysR[i]];
}
for (let i = 0; i < keysN.length; i++) {
refObj[keysN[i]] = newObj[keysN[i]];
}
}
For the example given by user3015682 you would use this function as following:
replaceReferencedObj(foo, {'bar': 2})
Assigning by reference and arrays.
let pizza = [4,4,4];
let kebab = pizza; // both variables are references to shared value
kebab.push(4);
console.log(kebab); //[4,4,4,4]
console.log(pizza); //[4,4,4,4]
Since original value isn't modified no new reference is created.
kebab = [6,6,6,6]; // value is reassigned
console.log(kebab); //[6,6,6,6]
console.log(pizza); //[4,4,4,4]
When the compound value in a variable is reassigned, a new reference is created.
Technically JS doesn't have pointers, but I discovered a way to imitate their behavior ;)
var car = {
make: 'Tesla',
nav: {
lat: undefined,
lng: undefined
}
};
var coords: {
center: {
get lat() { return car.nav.lat; }, // pointer LOL
get lng() { return car.nav.lng; } // pointer LOL
}
};
car.nav.lat = 555;
car.nav.lng = 777;
console.log('*** coords: ', coords.center.lat); // 555
console.log('*** coords: ', coords.center.lng); // 777

How to disable pointers usage in JS?

Why is the result {"a":"b","c":1}?
var foo = {"a":"b","c":0};
var bar = foo;
bar.c++;
alert(JSON.stringify(foo));
How to disable this behavior?
Both foo and bar variables reference the same object. It doesn't matter which reference you use to modify that object.
You cannot disable that behaviour, this is how JavaScript and many other major languages work. All you can do is to clone the object explicitly.
var foo = {"a":"b","c":0};
var bar = {"a":foo.a, "c": foo.c};
bar.c++;
What you're doing is making a second reference to an object but what it seems you want is a copy of that object instead.
If you want that functionality then you really want a copy function that copies all of the properties, one by one, into a new object:
// Take all the properties of 'obj' and copy them to a new object,
// then return that object
function copy(obj) {
var a = {};
for (var x in obj) a[x] = obj[x];
return a;
}
var foo = {"a":"b","c":0};
var bar = copy(foo);
bar.c++;
alert(JSON.stringify(foo));
and you'll get {"a":"b","c":0}
First, Javascript doesn't pass pointers, it passes references, slightly different. Secondly, there's no way to modify Javascript's default behavior, unfortunately fortunately.
What you might want to do is create a constructor and use that to create two similar, but separate instances of an object.
function Foo(a, b) {
this.a = a;
this.b = b;
}
var bar1 = new Foo(0, 0);
var bar2 = new Foo(0, 0);
bar2.b++;
console.log(bar1);
console.log(bar2);
>> {a:0, b:0};
>> {a:0, b:1};
You can't disable the way javascript works.
If you change a reference object, it effects all the object references...

How best to inherit from native JavaScript object? (Especially String)

I'm a long-time browser but a first time participator. If I'm missing any etiquette details, please just let me know!
Also, I've searched high and low, including this site, but I haven't found a clear and succinct explanation of exactly what I'm looking to do. If I just missed it, please point me in the right direction!
Alright, I want to extend some native JavaScript objects, such as Array and String. However, I do not want to actually extend them, but create new objects that inherit from them, then modify those.
For Array, this works:
var myArray = function (n){
this.push(n);
this.a = function (){
alert(this[0]);
};
}
myArray.prototype = Array.prototype;
var x = new myArray("foo");
x.a();
However, for String, the same doesn't work:
var myString = function (n){
this = n;
this.a = function (){
alert(this);
};
}
myString.prototype = String.prototype;
var x = new myString("foo");
x.a();
I've also tried:
myString.prototype = new String();
Now, in trying to research this, I've found that this does work:
var myString = function (n){
var s = new String(n);
s.a = function (){
alert(this);
};
return s;
}
var x = myString("foo");
x.a();
However, this almost feels like 'cheating' to me. Like, I should be using the "real" inheritance model, and not this shortcut.
So, my questions:
1) Can you tell me what I'm doing wrong as regards inheriting from String? (Preferably with a working example...)
2) Between the "real" inheritance example and the "shortcut" example, can you name any clear benefits or detriments to one way over the other? Or perhaps just some differences in how one would operate over the other functionally? (Because they look ultimately the same to me...)
Thanks All!
EDIT:
Thank you to everyone who commented/answered. I think #CMS's information is the best because:
1) He answered my String inheritance issue by pointing out that by partially redefining a String in my own string object I could make it work. (e.g. overriding toString and toValue)
2) That creating a new object that inherits from Array has limitations of its own that weren't immediately visible and can't be worked around, even by partially redefining Array.
From the above 2 things, I conclude that JavaScript's claim of inheritablity extends only to objects you create yourself, and that when it comes to native objects the whole model breaks down. (Which is probably why 90% of the examples you find are Pet->Dog or Human->Student, and not String->SuperString). Which could be explained by #chjj's answer that these objects are really meant to be primitive values, even though everything in JS seems to be an object, and should therefore be 100% inheritable.
If that conclusion is totally off, please correct me. And if it's accurate, then I'm sure this isn't news to anyone but myself - but thank you all again for commenting. I suppose I now have a choice to make:
Either go forward with parasitic inheritance (my second example that I now know the name for) and try to reduce its memory-usage impact if possible, or do something like #davin, #Jeff or #chjj suggested and either psudo-redefine or totally redefine these objects for myself (which seems a waste).
#CMS - compile your information into an answer and I'll choose it.
The painfully simple but flawed way of doing this would be:
var MyString = function() {};
MyString.prototype = new String();
What you're asking for is strange though because normally in JS, you aren't treating them as string objects, you're treating them as "string" types, as primitive values. Also, strings are not mutable at all. You can have any object act as though it were a string by specifying a .toString method:
var obj = {};
obj.toString = function() {
return this.value;
};
obj.value = 'hello';
console.log(obj + ' world!');
But obviously it wouldn't have any string methods. You can do inheritence a few ways. One of them is the "original" method javascript was supposed to use, and which you and I posted above, or:
var MyString = function() {};
var fn = function() {};
fn.prototype = String.prototype;
MyString.prototype = new fn();
This allows adding to a prototype chain without invoking a constructor.
The ES5 way would be:
MyString.prototype = Object.create(String.prototype, {
constructor: { value: MyString }
});
The non-standard, but most convenient way is:
MyString.prototype.__proto__ = String.prototype;
So, finally, what you could do is this:
var MyString = function(str) {
this._value = str;
};
// non-standard, this is just an example
MyString.prototype.__proto__ = String.prototype;
MyString.prototype.toString = function() {
return this._value;
};
The inherited string methods might work using that method, I'm not sure. I think they might because there's a toString method. It depends on how they're implemented internally by whatever particular JS engine. But they might not. You would have to simply define your own. Once again, what you're asking for is very strange.
You could also try invoking the parent constructor directly:
var MyString = function(str) {
String.call(this, str);
};
MyString.prototype.__proto__ = String.prototype;
But this is also slightly sketchy.
Whatever you're trying to do with this probably isn't worth it. I'm betting there's a better way of going about whatever you're trying to use this for.
If you want an absolutely reliable way of doing it:
// warning, not backwardly compatible with non-ES5 engines
var MyString = function(str) {
this._value = str;
};
Object.getOwnPropertyNames(String.prototype).forEach(function(key) {
var func = String.prototype[key];
MyString.prototype[key] = function() {
return func.apply(this._value, arguments);
};
});
That will curry on this._value to every String method. It will be interesting because your string will be mutable, unlike real javascript strings.
You could do this:
return this._value = func.apply(this._value, arguments);
Which would add an interesting dynamic. If you want it to return one of your strings instead of a native string:
return new MyString(func.apply(this._value, arguments));
Or simply:
this._value = func.apply(this._value, arguments);
return this;
There's a few ways to tackle it depending on the behavior you want.
Also, your string wont have length or indexes like javascript strings do, a way do solve this would be to put in the constructor:
var MyString = function(str) {
this._value = str;
this.length = str.length;
// very rough to instantiate
for (var i = 0, l = str.length; i < l; i++) {
this[i] = str[i];
}
};
Very hacky. Depending on implementation, you might just be able to invoke the constructor there to add indexes and length. You could also use a getter for the length if you want to use ES5.
Once again though, what you want to do here is not ideal by any means. It will be slow and unnecessary.
This line is not valid:
this = n;
this is not a valid lvalue. Meaning, you cannot assign to the value referenced by this. Ever. It's just not valid javascript. Your example will work if you do:
var myString = function (n){
this.prop = n;
this.a = function (){
alert(this.prop);
};
}
myString.prototype = new String; // or String.prototype;
var x = new myString("foo");
x.a();
Regarding your workaround, you should realise that all you're doing is making a String object, augmenting a function property, and then calling it. There is no inheritance taking place.
For example, if you execute x instanceof myString in my example above it evaluates to true, but in your example it isn't, because the function myString isn't a type, it's just a regular function.
You can't assign the this in a constructor
this=n is an error
Your myarray is just an alias for the native Array- any changes you make to myarray.prototype are changes to Array.prototype.
I would look into creating a new object, using the native object as a backing field and manually recreating the functions for the native objects. For some very rough, untested sample code...
var myString = {
_value = ''
,substring:_value.substring
,indexOf:_value.indexOf
}
Now, I'm sure this wont work as intended. But I think with some tweaking, it could resemble on object inherited from String.
The ECMAScript6 standard allows to inherit directly from the constructor functions of a native object.
class ExtendedNumber extends Number
{
constructor(value)
{
super(value);
}
add(argument)
{
return this + argument;
}
}
var number = new ExtendedNumber(2);
console.log(number instanceof Number); // true
console.log(number + 1); // 4
console.log(number.add(3)); // 5
console.log(Number(1)); // 1
In ECMAScript5 it is possible to inherit like this:
function ExtendedNumber(value)
{
if(!(this instanceof arguments.callee)) { return Number(value); }
var self = new Number(value);
self.add = function(argument)
{
return self + argument;
};
return self;
}
However, the generated objects are not primitive:
console.log(number); // ExtendedNumber {[[PrimitiveValue]]: 2}
But you can extend a primitiv type by extending his actual prototype that is used:
var str = "some text";
var proto = Object.getPrototypeOf(str);
proto.replaceAll = function(substring, newstring)
{
return this.replace(new RegExp(substring, 'g'), newstring);
}
console.log(str.replaceAll('e', 'E')); // somE tExt
A cast to a class-oriented notation is a bit tricky:
function ExtendedString(value)
{
if(this instanceof arguments.callee) { throw new Error("Calling " + arguments.callee.name + " as a constructor function is not allowed."); }
if(this.constructor != String) { value = value == undefined || value == null || value.constructor != String ? "" : value; arguments.callee.bind(Object.getPrototypeOf(value))(); return value; }
this.replaceAll = function(substring, newstring)
{
return this.replace(new RegExp(substring, 'g'), newstring);
}
}
console.log(!!ExtendedString("str").replaceAll); // true

JavaScript array of pointers like in C++

I'm faced with a situation in JavaScript when I need to update an object via its pointer similar to ะก++ array of pointers to objects
Example code for my issue:
var foo = new Array();
var bar = function(){
this.test = 1;
foo.push(this); // push an object (or a copy of object?) but not pointer
};
var barInst = new bar(); // create new instance
// foo[0].test equals 1
barInst.test = 2;
// now barInst.test equals 2 but
// foo[0].test still equals 1 but 2 is needed
So, how can I solve this? Should I use a callback or something like this or there is an easy way to help me to avoid copying the object instead pushing the raw pointer into an array?
JS is pass-by-value, so your original assignment was this.test = the value of 1, in my example, it's this.test = the object pointed to by ptr, so when I change ptr this.test changes as well.
var foo = [],
ptr = {val: 1},
bar = function(){
this.test = ptr;
foo.push(this); // push an object (or a copy of object?) but not pointer
},
barInst = new bar(); // create new instance
// foo[0].test.val equals 1
ptr.val = 2;
// foo[0].test.val equals 2
Although if you thought that foo.push(this); was similar, it isn't. Since this is an object, the array will indeed contain "raw pointers" to objects, just like you want. You can prove this simply:
foo[0].test = 3;
// barInst.test === 3
Which shows that it is indeed a pointer to the object that was pushed onto the array
"create object method pointer"
Object.defineProperty(Object.prototype,'pointer',{
value:function(arr, val){
return eval(
"this['"+arr.join("']['")+"']"+
((val!==undefined)?("="+JSON.stringify(val)):"")
);
}
});
ex of use
var o={a:1,b:{b1:2,b2:3},c:[1,2,3]}, arr=['b','b2']
o.pointer(arr) // value 3
o.pointer(['c',0], "new_value" )

diffrerent ways to create object in javascript

What is the differnce between following two?
obj = new Object();
OR
obj = {};
In my code am asked to replace first notation with second one and the code is huge.Will replacing it cause any problem?
According to JavaScript Patterns book, using a built-in constructor (obj = new Object();) is an anti pattern for several reasons:
it's longer to type than literal (obj = {};)
literal is preferred because it emphasizes that objects are mutable hashes
scope resolution - possibility that you have created your own (local) constructor with the same name (interpreter needs to look up the scope chain)
I will answer the second question:
Will replacing it cause any problem?
Nope, it won't cause any problem.
If you have for example those lines:
var obj = new Object("a");
//...code...
obj = new Object("b");
//...code...
Changing to this will have same result and no impacts:
var obj = { "a": 1 };
//...code...
obj = { "b": 2 };
//...code...
By assigning the variable with the = you're overwriting whatever it contained with the new value.
There is no difference. The former uses the Object constructor, whereas the latter is a literal, but there will be no difference in the resulting objects.
Greetings
Objects in JavaScript
1- var obj = { key1 : value1 , key2Asfunction : funciton1(){} };
obj.key1;
obj.key2Asfunction();
2- var obj = function()
{
this.obj1 = value1 ;
this.function1 = function(){};
}
var ob = new obj();
ob.obj1;
ob.function1();
if you need how to create the structure of the jquery frame work too i can help
Regrads :)

Categories

Resources