Question about Javascript properties and instances - javascript

I can't figure out myself why foo.bar in the example is undefined, could you explain?
var foo = "foo";
foo.bar = "baz";
console.log(foo.bar); // undefined
Q2: How do I add references to properties and methods to the String instance foo?
Help is appreciated, thanks.
-- EDIT --
Note: the question is about a generic String instance, not the String global object. So using "classic" prototyping as someone suggested is not an option, because this way every String instance would have a property called bar, while I want to augment only certain instances.

This is a duplicate of Why can't I add properties to a string object in javascript?.
Basically, you're creating a string, and this is a primitive type in javascript.
You cannot add properties to primitive types in javascript.

By using a real String object for foo:
var foo = new String('foo');
foo.bar = 'baz';
console.log(foo.bar); // 'baz'

foo.bar = "baz"; is the same as undefined = "baz";
You can add functions to string by using it's prototype;
String.prototype.bar = function() {
return "baz";
};
foo.bar() ; //# => baz

When you specified var foo = "foo"; you are asking foo to be interpreted as a string. String can only have a literal as a value. It cannot have any other sub-properties. ( just extend this logic to any other oo programming language you know and it will become clearer). Instead you could do something like this.
var fooObject = new Object()
fooObject.foo = "foo"
fooObject.bar = "baz"

You're talking about "prototyping", which is the ability to add custom properties to objects in javascript.
This is an excellent and concise tutorial on prototyping:
http://www.javascriptkit.com/javatutors/proto.shtml

To extend the String class, modify its prototype:
String.prototype.bar = "baz";
var foo = "foo";
console.log(foo); // "foo"
console.log(foo.bar); // "baz"
In your question, you were modifying an instance of the String class instead of the String class itself.

Related

What's substantive difference between function and Object in javascript?

When I learn js at first I get a voice which say everything is an object, so I think maybe function is an object and object is an object too.
But when I learn prototype, some thing different to my thought.
function helloworld(){
this.hi = 'world';
}
var foo = {
'sth':'happend'
};
function bar(){};
bar.prototype = foo;
console.log(new bar().sth);
bar.prototype = helloworld;
console.log(new bar().hi);
And I get print
happend
undefined
Then I replace bar.prototype = helloworld; to bar.prototype = new helloworld(); I get correct result.
happend
world
I'm a newbie, maybe it's a stupid question, but I really want to know what's wrong in my mind? is function not an Object? could anybody help me? thanks a lot..
Yes, a function is an object, and can have properties as well:
var foo = {};
var bar = function(x){return x+1};
foo.prop = "hello ";
bar.prop = "world!"; // works the same!
alert(foo.prop + bar.prop);
What's substantive difference between function and Object?
Well, a function is an object that can be called - "normal" objects can't:
bar(4); // 5
foo(4); // Error: 'foo' is not a function
I replace bar.prototype = helloworld; with bar.prototype = new helloworld(); to get correct result
I really want to know what's wrong in my mind?
You must not confuse constructor functions for instances that were created by calling them. helloworld is an object (just as bar is in the example above), but it's a very different object than new helloworld() (which inherits from helloworld.prototype, and was initialised by the constructor with a hi property).

Are javascript objects "open" like Ruby?

In Ruby, I can add and modify functionality of any class, object, or method using the same syntax I would to declare my own because Ruby has "open classes".
Is javascript like that?
.
As an example...
In my case, I want to change the way Google Apps Script handles URL objects so that every time I evaluate a URL object, the URL object itself makes sure it begins with a protocol :// (http:// by default).
Yes, you can modify objects freely. You can modify a particular object Object.overridenProperty = ..., or modify all objects derived from a given class via its prototype property Object.prototype.inheritedMethod = ....
Have in mind that redefining a method can be tricky, as the new definition won't share the same scope as the original definition:
var BaseClass;
(function(){
var defaults = { ... };
BaseClass = function(){
this.someValue = defaults.someValue;
};
}());
It could also happen that the class definition lies inside a closure and you have no practical way to override a method or property as it is generated JIT. In that case you'd need to override the property at each object you are interested in individually:
(function(){
var defaults = { ... },
BaseObject = (function(){
var obj = function(){
this.someValue = defaults.someValue;
};
return obj;
}());
}());
Yes.
With the caveat that how you define a "class" is pretty different than in Ruby. But you can achieve the same effect.
This ruby:
#ruby
class Foo
# no methods yet
end
foo = Foo.new
class Foo
def bar
'bar'
end
end
foo.bar #=> 'bar'
Would have this equivalent JavaScript implementation:
// js
var Foo = function() {};
var foo = new Foo();
Foo.prototype.bar = function() {
return 'bar';
};
foo.bar(); // 'bar'
You can even override things just as easily:
var oldBar = Foo.prototype.bar;
Foo.prototype.bar = function() {
return "Called oldBar and got: "+ oldBar.call(this);
};
foo.bar(); // "Called oldBar and got: bar"
see this class with getter and setter:
function User(){
this._name = "";
}
User.prototype.setName = function(name){this._name = name;}
User.prototype.getName = function(){return this._name;}
user = new User();
user.setName("somename");
alert(user.getName(););
JSfiddle Example
You've specifically mentioned Google Apps Script in your question. Since GAS is a variant of JavaScript, the "usual methods" of object definition and extension apply, as covered in the other answers.
However, there's one terribly annoying exception: You cannot extend prototypes of Google's Classes. You can find comments about this on the issue tracker, Issue 708. It's been marked "Won't Fix".

Why declare a variable as a new Object?

As a beginner, working with existing code, I've come across the following:
var foo = {};
which I believe is equivalent to:
var foo = new Object();
I was under the impression that any variable was automatically an Object, so what would be the purpose of specifically coding that, rather than just declaring an empty variable:
var foo;
I was under the impression that any variable was automatically an Object
That is a mistaken impression. If you declare a variable and do not assign it a value, it is initialised to undefined (as mention in the spec and described in detail), which is not an object (it's a primitive value):
var foo;
console.log(foo); // undefined
If you were to attempt to set a property of an undefined variable you would receive a TypeError:
var foo;
foo.example = "hello"; // TypeError: Cannot set property 'example' of undefined
However, if you assign an empty object to that variable, the above code will succeed:
var foo = {}; // Now refers to an empty object (equivalent to `new Object()`)
foo.example = "hello";
console.log(foo); // '{example:"hello"}'
I believe your understanding probably stems from the common misunderstanding that "everything in JavaScript is an object". This is not true. Many things in JavaScript are objects, but primitive values are not. For example:
var a = "hello"; // String primitive, not an object
var b = new String("hello"); // String instance, object
var c = 10; // Number primitive, not an object
var d = true; // Boolean primitive, not an object
var e; // Undefined value, not an object
var f = null; // Null value, not an object
James's answer is correct. In case he's throwing too much info too quickly (refer back to it later, if so), here's a quick summary.
You are correct in this: var foo = {} and var foo = new Object() are not only equivalent, the results are identical. Only use object literals. (ignore new Object(), new Array(), etc).
var foo; does nothing other than declare a variable. It is 'undefined' by default.
var foo = new Object() also gives the new object a prototype property which can be used to manipulate object inheritance and call standard object functions defined by javascript
see here for details on how you can manipulate the object.protype:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/prototype

What does the object[foo] term mean?

I'm confused what the object[foo] term is referring to. Any hints? I know that bar['unique_prop'] and bar.unique_prop refers to 2
var foo = {unique_prop: 1};
var bar = {unique_prop: 2};
var object = {};
object[foo] = 'value';
alert(object[bar]);
code on jsfiddle
This:
var foo = 'abc';
object[foo]
is equivalent to:
object.abc
However this:
var foo = {unique_prop: 1};
object[foo] = 'value';
Doesn't have much sense (object property names cannot be object literals). JS engine will use foo.toString() (returning e.g. "[object Object]"), so in fact you are doing this:
var foo = {unique_prop: 1};
object["[object Object]"] = 'value';
which is clearly a bug or a misunderstanding. This behaviour is explained in Member Operators on MDN:
Property names must be strings. This means that non-string objects cannot be used as keys in the object. Any non-string object, including a number, is typecasted into a string via the toString method.
You can however use:
object[foo.unique_prop] = 'value';
which is equivalent to:
object[1] = 'value';
It is the same as object.whatever_x_is where x is foo.toString() which will be the same as bar.toString() since (unless overridden) calling toString on a generic object will generate a generic "is an object" string such as "[object Object]"
object[foo] = 'value';
attempts to use an object as a member name, this causes a .toString() call so;
'value' is assigned to object["[object Object]"], when you attempt to read alert(object[bar]); the same toString() occurs as bar is also an object, so you reference object["[object Object]"] once again and get back 'value'.

Difference between var someObj = {}; and var someObj = new RealObj

So this is more of a question due to "not knowing the right word, thus I can't google it up" (I think).
What I have been wondering with javascript. One can create two "types" of Objects.
One would be: (or through using prototypes)
function Foo(){
this.bar = function(){};
}
var foo = new Foo();
The other one being:
var foo = {
bar : function(){}
};
The only few differences that I can come up with would be the fact that the former uses prototypes and can "extend" from other objects and also allows multiple instances where the latter can only have one instance and can't be extended (in the same way) (correct me if I am wrong)
However, in this case the variable named var foo has the exact same properties in both cases.
So for a concrete question: what is the name of the type of object being created (how can I search for more information on google for it) in the latter version and what differences are there between the two ways of creating an object?
The differences you are describing are correct.
The latter is called object literal notation and is more concise if you just want to create one object. But they are not two different types of objects. The object literal notation is more like a shortcut (but preferred) for creating objects.
You might want to read MDC - Working with objects.
The literal notation is actually the same as doing:
var foo = new Object();
foo.bar = function() {};
but as already said, it is more concise and easier to read.
Update:
Maybe one further difference worth mentioning: Calling new Foo() does not necessarily mean you will get a "Foo object" back. A constructor function can return any object. E.g. this is valid:
function Foo() {
return new Bar();
}
var foo = new Foo(); // foo contains a "Bar object"
This can become useful for inheritance or if you want to e.g. cache instances and return the same instance for the same parameters passed to the function.
When you define an object using:
var foo = {};
It is literal. That object is an instant instance of the object. When you define an object like:
function Foo(){
this.bar = function(){};
}
There is no instance created until you do new Foo().

Categories