I have a basic understanding of instanceof in JavaScript, testing if the left hand side object "is of" the right hand side object type. The following 2 examples help me understand that...
var demo1 = function() {};
demo1.prototype = {
foo: "hello"
};
var demo2 = function() {
var pub = {
bar:"world"
};
return this.pub;
};
var obj1 = new demo1();
var obj2 = new demo2();
console.log(obj1 instanceof demo1); //returns true
console.log(obj2 instanceof demo2); //returns true
But on this 3rd example, I get false and I don't understand why....
var o = {}; // new Object;
o.toString(); // [object Object]
console.log(o instanceof toString); //returns false
Thanks for any help in understanding whats going on. Also...is is possible to make the 3rd example true?
Thanks again
toString does not cause a type change of o. It just returns a string representation of the object, without altering it. So, o is still a simple object and no instanceof String.
var o = {}; // new Object object
var ostring = o.toString(); // "[object Object]"
typeof o; // object
typeof ostring; // string - this is a primitive value, not an object; so that
ostring instanceof String; // is false
var stringobj = new String(ostring); // new String object
typeof stringobj; // object
stringobj instanceof String; // true!
o instanceof Object; // also true!
See also MDN reference for the String constructor.
o is an object; toString is a function. They are different types in JavaScript.
alert(typeof(o)); //"object"
alert(typeof(toString)); //"function"
JavaScript makes a distinction between objects and functions. Therefore, that's why you get false returned in your example.
With an object literal like
var o = {}; // new Object;
you create an object whose prototype is Object. Testing with instanceof will not yield any useful information. The only comparison that will yield true is
o instanceof Object
Related
This question is based on previous question:
Difference in these 2 Strings (JavaScript)
The people replied that there is a difference by creating string via 2 separate ways:
String Literal creates string (var a = "abc")
new keyword creates string-object, I assume it is a kind of object (var b = new String("def"))
Now, typeof in 1st case will return string. In 2nd case it will return Object. I am okay, there might be certain way of working, of JS engine, by the people who developed it.
But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above. Now I am really confused, new String is either creating a string, or object or what? It is just NOT consistent!
Can someone help me explain?
var obj1 = new Object({name: "Peter"});
var obj2 = new Object({age: 29});
var str1 = new String("abc");
var str2 = new String("def");
console.log(obj1);
console.log(obj2);
console.log(str1);
console.log(str2);
console.log(obj1 + obj2);
console.log(str1 + str2);
new String creates a String object, which inherits from Object, but has its own .toString and .valueOf methods, so it will print the string content.
var o = new Object();
var s = new String("foo");
console.log(o.toString === s.toString); // false
console.log(o.valueOf === s.valueOf); // false
You can override them with your own to see that they're invoked. Just be sure to invoke the originals too.
var s = new String("foo");
s.valueOf = function() {
console.log("custom valueOf");
return String.prototype.valueOf.call(this);
}
s.toString = function() {
console.log("custom toString");
return String.prototype.toString.call(this);
}
console.log(s + s);
[""].join(s);
But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above.
The difference is a String object has a default valueOf method that returns the string value contained within the object.
The Object object has a more generic valueOf method which simply returns a string of [object Object]
See -
const one =
{ valueOf: _ => 1 }
const two =
{ valueOf: _ => 2 }
console.log(one + two)
// 3
You can define valueOf to be anything -
const foo =
{ valueOf: _ => "foo" }
const bar =
{ valueOf: _ => "bar" }
console.log(foo + bar)
// "foobar"
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.
What's the best way to check the type for objects created by Object.create or literal, for example the following code. I want to make sure the arguments to the function is safe to use. Maybe I shouldn't check the type of arguments, but check whether the properties the function uses are not undefined. But it seems very tedious to do so. What's the best approach, thanks.
var base = {
name : "abc"
};
var child = Object.create(base);
do_something = function(o) {
if (typeof(o) === "base") { // will not work
...
}
}
typeof can only return the base type like, object, strirng, number, undefined.
typeof o === "object"
instanceof can be used if you are inheriting from the base class. Eg here MDN
function Base() {
this.name = "abc";
}
var child = new Base();
var a = child instanceof Base; //true
instance of expects the format <object> insanceof <function>
You can use isPrototypeOf() when inheriting using Object.create()
var base = {name; "abc"};
var child = Object.create(base);
base.isPrototypeOf(child);
More info can be read here: Mozilla Developer Network: isPrototypeOf
To check if there exists an object o with the attribute name non empty, you can do
if(typeof o === "object" && typeof o.name !== "undefined")
A shorthand can be used, if name will not hold falsy values like 0
if(o && o.name)
In your code base is a variable not a type, In JavaScript function are treated as classes if you want base type then create a function and initialize it and then use instanceof that will give you base.
Try this way using instanceof:
var base = function(){
name : "abc"
};
var o = new base();
alert(o instanceof base); // true
Here is JsFiddle
I have try three way in the bellow, the result is comment on the right,the diffcult is I can't different it from Object datatype.How can I get it datatype like Array or String but not Object?
var arr = [];
console.log('type of arr', typeof arr); //objct
console.log('instanceof array', arr instanceof Array); //true
console.log('instanceof object', arr instanceof Object); // true
Here is one technique:
> var arr = [];
> Object.prototype.toString.call(arr);
"[object Array]"
What this does is call the toString method of the prototype object, using whatever is passed in as the this pointer. For more information on this technique, see the reference on call.
It turns out that you can use this technique to figure out other object types as well:
> var func = function(){}
> Object.prototype.toString.call(func);
"[object Function]"
> var obj = {};
> Object.prototype.toString.call(obj);
"[object Object]"
you can use jQuery's "isArray" function for this
var arr1 =[];
alert(jQuery.isArray(arr1)); // true
var arr2 = new Array();
alert(jQuery.isArray(arr2)); // true
var obj = new Object();
alert(jQuery.isArray(obj)); // false
I got this info at MDN - In Javascript Version 1.8.5 Array.isArray is added and it is standard in ECMAScript 5
// all following calls return true
Array.isArray([]);
Array.isArray([1]);
Array.isArray( new Array() );
Array.isArray( Array.prototype ); // Little known fact: Array.prototype itself is an array.
Also if isArray is not available
if(!Array.isArray) {
Array.isArray = function (vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
};
}
For more details at MDN
Array always will be instance of object - Object is the base object in javascript and any another object created by new is inherited from.
new String('a') instanceof Object // true - also instance of String
new Number(3) instanceof Object // true -also instance of Number etc.
new Boolean(true) instanceof Object // true
new Date instanceof Object // true
new function(){} instanceof Object // true
[] instanceof Object // true - [] is equal to new Array
check this out:
Array = 1;
[] //TypeError: Cannot read property 'slice' of undefined
:)
however
'a' instanceof Object // false
3 instanceof Object // false
Try this:
var str = 'aaa',
arr = [],
myClass = function(){},
myClassInstance = new myClass;
str.constructor == String // true
arr.constructor == Array // true
myClassInstance.constructor == myClass // true
This is very simple, your question is your answer indeed,
var arr = [];
if('instanceof object', arr instanceof Object){
alert('arr is a object');
if('instanceof array', arr instanceof Array){
alert('arr is a Array');
}
}else{
alert('this is not a object');
}
Now let's use a simple variable testObj, This is not even a object then how it could be a array,
var testObj;
if('instanceof object', testObj instanceof Object){
alert('testObj is a object');
}else{
alert('testObj is not a object');
}
Try this for more
What does the Object function in JavaScript do?
For example, what happens when we do Object(1)?
It forces something to be an object. I've not seen it being used in this way though.
var num = 1;
var obj = Object(num);
alert(typeof num); //displays "number"
alert(typeof obj): //displays "object"
alert(num + "," + obj); //displays "1,1"
The preferred, faster way to create an empty object on which you can put properties and methods on is by using {}. Three possible ways to create an object:
var emptyObj = {};
var emptyObj = new Object();
var emptyObj = new Object; // Object does not need an argument, so this is valid.
From the Mozilla developer site:
The Object constructor creates an object wrapper for the given value. If the value is null or undefined, it will create and return an empty object, otherwise, it will return an object of type that corresponds to the given value.
When called in a non-constructor context, Object behaves identically.
So Object(1) produces an object that behaves similarly to the primitive value 1, but with support for object features like assigning values to properties (Object(1).foo = 2 will work, (1).foo = 2 will not).
var obj = Object("test");
Creates a String "text", it's pretty similar to
var obj2 = "test";
Notice that the type of obj2 is "String" and of obj1 "Object"
Try this:
<script>
var obj = Object("test");
console.log(obj);
console.log(typeof(obj));
console.log(obj["0"]);
obj2 = "test";
console.log(obj2);
console.log(typeof(obj2));
console.log(obj2["0"]);
</script>
Creates an object http://www.w3schools.com/js/js_objects.asp
Object function is a constructor function, all other types(like Array, String, Number) inheritate it.