Checking if data is immutable
What is the quickest and cleanest way to test if a var
holds immutable data (i.e. is string
, number
, boolean
, null
, undefined
)?
E.g. When var test
is mutable, the following is legal:
var test = {};
//the next 2 lines work because `test` has mutable data
test.someFun = function () { alert(this); };
test.someFun();
but when var test
is immutable, it's illegal:
var test = "string";
//the next 2 lines are invalid, as `test` is a primitive
test.someFun = function () { alert(this); };
test.someFun(); 开发者_如何学JAVA
Just another short option:
function isPrimitive(value) {
return Object(value) !== value;
}
How does it works:
If the value
is a primitive value that is convertible to object, such as a Number
, String
or a Boolean
, the strict equality operator will return true, since the Object
constructor called as a function, will convert the value to a "wrapped object":
typeof 5; // "number"
typeof Object(5); // "object", a wrapped primitive
5 === Object(5); // false
If the value is a primitive not convertible to Object, such as null
or undefined
, the Object constructor will create a new empty object, returning true.
The last case, if value
holds a reference to an object, the Object
constructor will do nothing, and the strict equality operator will return false
.
isMutable = function (test) {
return test !== null && (typeof test == 'object' || typeof test == 'function');
}
var test = {};
if(test instanceof Object){
test.someFun = function () { alert(this); };
test.someFun();
}
jball pointed out the following:
For the instanceof check to work, the left-hand side object should be from the same scope as the right-hand side object. This is because even the common JavaScript objects have different copies in different scopes, i.e.
window1.String !== window2.String.
(Quote MDN)
Seems a valid point to me. So if you want to do this check across different scopes you will need to use the workaround:
var test = {};
if(test && (typeof test == 'object' || typeof test == 'function')){
test.someFun = function () { alert(this); };
test.someFun();
}
I would try to avoid the use of iframes though.
The null check is needed because typeof(null)
is equal to 'object'
.
EDIT:
box9 and jball did some performance testing on all the methods proposed (+1 for that). I used Chrome, Firefox and Internet Explorer. The result are as expected. These two methods are the fastest. On Chrome and Firefox the typeof
version is the fastest. On Internet Explorer the instanceof
version was the fastest. But the difference in speed between these two methods were minor. Personally I'd still go with the instanceof
method if I could because it's cleaner.
Nice and short, just for fun (no &&
or ||
s):
function isMutable(o) {
return /(object)|(function)/.test(typeof(o||0));
}
Why don't you try
if you're not sure?
精彩评论