Home>

In JavaScript, we often see code that compares a variable to null (this usage is very problematic) to determine whether a variable is assigned a reasonable value.such as:

var controller={
process:function (items) {
if (items! == null) {// bad writing
items.sort ();
items.foreach (function (item) {
// execute some logic
});
}
}
}

In this code, The process () method obviously wants items to be an array,Because we see that items have sort () and foreach (). The intent of this code is pretty obvious:if the parameter items is not a group number,Then stop the next operation.The problem with this writing is thatA comparison with null does not really prevent errors. The value of items can be 1 or a string.It can even be any object.These values ​​are not equal to null, which will cause an error in the process () method once it reaches sort ().

Just comparing with null does not provide enough information to determine whether subsequent code execution is really safe.Fortunately, JavaScript provides us many ways to detect the true value of a variable.

Detect raw values

There are 5 primitive types (also known as simple data types) in JavaScript:string, number, boolean, undefined, and null. If i want a value to be string, number, boolean, or undefined, the best choice is to use the typeof operator, which returns a string representing the type.

For strings, typeof returns "string".

For numbers, typeof returns "number".

For Boolean values, typeof returns "boolean".

For undefined, typeof returns "undefined".

The basic syntax of typeof is:typeof variable, you can also use:typeof (variable), although this is legal javascript syntax, this usage makes typeof look like a function instead of an operator.In view of this, we recommend the wording without brackets.

It is very safe to use typeof to detect these 4 primitive types.Take a look at these examples.

// detect "string"
if (typeof name === "string") {
anothername=name.substring (3);
}
// detect "number"
if (typeof count === "number") {
updatecount (count);
}
// detect "boolean"
if (typeof found === "boolean" && found) {
message ("found!");
}
// detect "undefined"
if (typeof myapp === "undefined") {
myapp={
// other code
};
}

The typeof operator is unique in thatIt's not an error to use it for an undeclared variable.Both undefined variables and variables with the value undefined will return "undefined" via typeof.

The last primitive type, null, will return "object" via typeof, which looks weird,It is considered a serious bug in the standard specification, so the use of typeof to detect null types should be avoided when programming.

console.log (typeof null);// "object"

A simple comparison with null usually doesn't contain enough information to determine if the value type is legal,So null is generally not used for detecting statements.

There is one exception,If the expected value is really null, you can compare directly with null.E.g:

// If you need to detect null, use this method
var element=document.getelementbyid ("my-div");
if (element! == null) {
element.classname="found";
}

If the dom element does not exist,The value obtained by document.getelementbyid () is null. This method either returns a node,Either null is returned. Since null is a predictable output at this time,You can use the identity operator === or the non-identity operator! == to check the return result.

The typeof operator returns a function in addition to the string, number, boolean, undefined, and object mentioned above. From a technical perspective,Functions are also objects in JavaScript,Not a data type.However, functions do have some special properties,It is therefore necessary to distinguish functions from other objects by the typeof operator.This feature will be used later in the detection function.

Detect reference values

Except for primitive values ​​in JavaScript, all are reference values ​​(also called objects). Common reference types are:object, array, date, and regexp. These reference types are all built-in objects of javascript. The typeof operator returns "object" when determining these reference types.

console.log (typeof {});// "object"
console.log (typeof []);// "object"
console.log (typeof new date ());// "object"
console.log (typeof new regexp ());// "object"

The best way to detect a reference value type is to use the instanceof operator. The basic syntax of instanceof is:

value instanceof constructor
// detection date
if (value instanceof date) {
console.log (value.getfullyear);
}
// detect error
if (value instanceof error) {
throw value;
}
// detect regular expression
if (value instanceof regexp) {
if (value.test (anothervalue)) {
console.log ("matches");
}
}

An interesting feature of instanceof is that it not only detects the constructor that constructs this objectThe prototype chain is also tested.The prototype chain contains a lot of information,Includes the inheritance pattern used to define objects.For example, by default,Every object inherits from object, so the value instanceof object of each object returns ture. such as:

var now=new date ();
console.log (now instanceof object);// ture
console.log (now instanceof date);// ture
The instanceof operator can also detect custom types,such as:
function person (name) {
this.name=name;
}
var me=new person ("nicholas");
console.log (me instanceof object);// ture
console.log (me instanceof person);// ture

The person type is created in this sample code. The variable me is an instance of person, so me instanceof person is true. As mentioned earlier,All objects are considered instances of object, so me instanceof object is also ture.

When detecting built-in types and custom types in JavaScript, the best practice is to use the instanceof operator, which is the only way.

But there is a serious limitation,Assuming that both browser frames have the constructor person, and the person instance frameapersoninstance in frame a is passed to frame b, the result will be as follows:

console.log (frameapersoninstance instanceof frameaperson) // ture

console.log (frameapersoninstance instanceof framebperson) // false

Although the definition of two persons is exactly the same,But in different frames, they are considered different types.There are two very important built-in types that have this problem:array and function, so they are generally not detected using instanceof.

Detection function

Technically,Functions in javascript are reference types,There is also a function constructor,Each function is its instance,such as:

function myfunc () {}
// bad writing
console.log (myfunc instanceof function);// true

However, this method cannot be used across frames, because each frame has its own function constructor,Fortunately, the typeof operator can also be used in functions.Returns "function".

function myfunc () {}
// good writing
console.log (typeof myfunc === "function");// true

The best way to detect a function is to use typeof because it can be used across frames.

There is a limit to using typeof to test functions.In ie 8 and earlier ie browsers,Use typeof to detect that functions in the dom node all return "object" instead of "function". such as:

// ie8 and earlier versions of ie
console.log (typeof document.createelement);// "object"
console.log (typeof document.getelementbyid);// "object"
console.log (typeof document.getelementbytagname);// "object"

This weird phenomenon occurs because browsers implement dom differently.In short, these earlier versions of Internet Explorer did not implement dom as a built-in javascript method, causing the built-in typeof operator to recognize these functions as objects.Because dom is clearly defined,Knowing that the existence of an object member means that it is a method,Developers often use the in operator to detect dom methods, such as:

// detect dom method
if ("queryselectorall" in document) {
var images=document.queryselectorall ("img");
}

This code checks whether queryselectorall is defined in the document, and if so, uses this method.Although not the most ideal method,If i want to detect the existence of the dom method in Internet Explorer 8 and earlier,This is the safest practice.In all other cases, The typeof operator is the best choice for detecting javascript functions.

Detect array

One of the oldest cross-domain issues in JavaScript is passing arrays back and forth between frames.Developers soon discovered that instanceof array would not return the correct results in this scenario.As mentioned above,Each frame has its own array constructor,So instances in one frame are not recognized in another frame.

Much research has been done on how to detect array types in JavaScript,In the end kangax came up with an elegant solution:

function isarray (value) {
return object.prototype.tostring.call (value) === "[object array]";
}

kangax found that calling the value of the built-in tostring () method returns a standard string result in all browsers.For arrays,The returned string is "[object array]", regardless of which frame the array instance is actually constructed from.This method is often useful when identifying built-in objects,Do not use this method for custom objects.

ecmascript5 officially introduces array.isarray () to javascript. The sole purpose is to accurately detect whether a value is an array.As with kangax, array.isarray () can also detect values ​​passed across frames,So many javascript libraries currently implement this method similarly.

function isarray (value) {
if (typeof array.isarray === "function") {
return array.isarray (value);
} else {
return object.prototype.tostring.call (value) === "[object array]";
}
}

ie 9+, firefox 4+, safari 5+, opera 10.5+, and chrome all implement the array.isarray () method.

Detect attributes

Another scenario that uses null (and undefined) is when detecting whether a property exists in an object,such as:

// Bad writing:detecting false values
if (object [propertyname]) {
// some code
}
// Bad writing:compared with null
if (object [propertyname]!=null) {
// some code
}
// Bad writing:compared with undefined
if (object [propertyname]!=undefined) {
// some code
}

Every judgment in the above code,Actually check the value of the attribute by the given name,It does not determine whether the attribute pointed to by the given name exists.In the first judgment,The result will be wrong when the attribute value is false,For example:0, "" (empty string), false, null, and undefined, after all, these are legal values ​​for attributes.

The best way to tell if an attribute exists is to use the in operator. The in operator simply determines whether the attribute exists,Without reading the value of the attribute,If the properties of the instance object exist or inherit from the object's prototype, The in operator always returns true. such as:

var object={
count:0,related:null
};
// good writing
if ("count" in object) {
// the code here will execute
}
// Bad writing:detecting false values
if (object ["count"]) {
// the code here will not execute
}
// good writing
if ("related" in object) {
// the code here will execute
}
// bad writing,Check if
if (object ["related"]!=null) {
// the code here will not execute
}

If you just want to check if a property of an instance object exists,Use the hasownproperty () method. All javascript objects that inherit from object have this method,Returns true if this property exists in the instance (if this property exists only in the prototype,Returns false). have to be aware of is,In Internet Explorer 8 and earlier, the dom object does not inherit from object and therefore does not include this method.That is,You should check for the existence of the dom object's hasownproperty () method before calling it.

// for all non-dom objects,This is good writing
if (object.hasownproperty ("related")) {
// executing this code will
}
// If you are not sure if it is a dom object, write it like this
if ("hasownproperty" in object &&object.hasownproperty ("related")) {
// executing this code will
}

Because of the existence of Internet Explorer 8 and earlier, when determining whether the properties of the instance object exist,I prefer the in operator, and hasownproperty () is used only when I need to determine instance properties.

Whenever you need to detect the existence of an attribute,Use the in operator or hasownproperty (). This can avoid many bugs.

  • Previous Chapter 4 Bootstrap Grid System Offset and Nested Columns
  • Next Summary of python regular expression learning
  • Trends