类型


JavaScript提供了多个内置的数据类型。 除了这些, 此页面文档增加了虚拟类型,如选择器, 增强的伪类型,如事件,和所有你想知道的一切功能。

你应该可以尝试下面大多数的示例, 只要将它们复制到浏览器的JavaScript控制台 (Chrome, Safari 用开发菜单激活, IE 8+) 或 Firebug 控制台 (Firefox)。

每当一个例子提到一个类型默认为一个布尔值, 其结果是很好的了解,在布尔环境使用该类型:

1
2
3
4
5
6
var x = "";
if ( x ) {
console.log( "x defaulted to true" );
} else {
console.log( "x defaulted to false" );
}

在这种情况下, "x defaulted to false" 被打印出来了.

为了保持例子间短, 转换(“非”)操作, 和 双重否定是用来显示一个布尔上下文:

1
2
3
var x = "";
!x // true
!!x // false (双重否定: 因为 "非 (空字符串)" 为 true,再次否定让它变成 false)

显示实际的类型。

如图:

内容

  1. String
  2. htmlString
  3. Number
  4. Boolean
  5. Object
  6. Array
  7. PlainObject
  8. Date
  9. Function
  10. Selector
  11. Event
  12. Element
  13. jQuery
  14. XMLHttpRequest
  15. jqXHR
  16. Deferred Object
  17. Promise Object
  18. Callbacks Object
  19. XML Document

String

字符串在JavaScript中是一个不可变对象, 包含零个,一个或多个字符。

1
2
"I'm a String in JavaScript!"
'So am I!'

字符串类型是"string"。

1
typeof "some string"; // "string"

Quoting

字符串可以使用单引号或双引号来定义。 您可以双引号内嵌套单引号, 也可以单引号内嵌套双引号。 混合双引号与双引号(或单引号与单引号), 嵌套的内容必须用一个反斜杠转义。

1
2
3
"You make 'me' sad."
'That\'s "cranking" good fun!'
"<a href=\"home\">Home</a>"

Built-in Methods(内置的方法)

JavaScript中的字符串有一些内置的方法来操作字符串,  虽然结果总是一个新的字符串 - 或其他什么东西, 例如:split返回一个 array

1
2
3
4
5
"hello".charAt( 0 ) // "h"
"hello".toUpperCase() // "HELLO"
"Hello".toLowerCase() // "hello"
"hello".replace( /e|o/g, "x" ) // "hxllx"
"1,2,3".split( "," ) // [ "1", "2", "3" ]

length属性

所有字符串都有一个length属性(愚人码头注释:字符串长度)。

1
2
"Hello".length // 5
"".length // 0

Boolean 缺省

空字符串默认为false:

1
2
3
4
5
!"" // true
!!"" // false
!"hello" // false
!"true" // false
!new Boolean( false ) // false

htmlString

当一个字符串被用于表示一个或多个DOM元素时候,那么在jQuery文档中这个字符串会被指定为htmlString, 通常被创建并插入到文档中。 当一个字符串作为参数传递给jQuery()函数时,如果该字符串以<tag ... >开始, 那么该字符串直到最后的>字符会被认为 并且 解析为HTML。 在jQuery1.9之前,如果一个字符串只要包含<tag ... >(愚人码头注:<tag ... >在字符串的任何位置),那么该字符串都会被认为是HTML。

当一个字符串作为参数传递到一个操作方法,例如, .append()方法, 它总是被认为是HTML, 因为jQuery对字符串的其他常见的阐释(CSS选择器) 并不适用于这些环境。

要将一个字符串明确解析为HTML,从jQuery1.8开始, $.parseHTML() 方法是非常有效的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Appends <b>hello</b>:
$( "<b>hello</b>" ).appendTo( "body" );
// Appends <b>hello</b>:
$( "<b>hello</b>bye" ).appendTo( "body" );
// Syntax error, unrecognized expression: bye<b>hello</b>
$( "bye<b>hello</b>" ).appendTo( "body" );
// Appends bye<b>hello</b>:
$( $.parseHTML( "bye<b>hello</b>" ) ).appendTo( "body" );
// Appends <b>hello</b>wait<b>bye</b>:
$( "<b>hello</b>wait<b>bye</b>" ).appendTo( "body" );

Number

在JavaScript中的数字是双精度64位格式的IEEE 754( 二进制浮点数算术标准)值。 就像字符串类型一样,他们是不可变的。 所有基于C的语言都可以有效的使用 (+, -, *, /, %, =, +=, -=, *=, /=, ++, --)操作数字。

1
2
12
3.543

数字的类型是"number"。

1
2
typeof 12 // "number"
typeof 3.543 // "number"

Boolean 缺省值

如果一个数字是0, 那么默认是 false:

1
2
3
4
!0 // true
!!0 // false
!1 // false
!-1 // false

由于数字为双精度值实现的, 下面的结果不是一个错误:

1
0.1 + 0.2 // 0.30000000000000004


Math

JavaScript在 在Math对象中提供了数字实用工具:

1
2
Math.PI // 3.141592653589793
Math.cos( Math.PI ) // -1

解析为数字

parseInt函数和parseFloat帮助解析字符串转换为数字。如果没有指定要解析的数字的基数, 那么将做隐式转换:

1
2
3
4
5
6
parseInt( "123" ) = 123 // (implicit decimal)
parseInt( "010" ) = 8 // (implicit octal)
parseInt( "0xCAFE" ) = 51966 // (implicit hexadecimal)
parseInt( "010", 10 ) = 10 // (explicit decimal)
parseInt( "11", 2 ) = 3 // (explicit binary)
parseFloat( "10.10" ) = 10.1

数字转化为字符串

当数字加上字符串时候, 结果始终是一个字符串。 操作是一样的,所以要小心: 如果你想先数字相加,那么先用括号括起来,然后将它们和一个字符串相加:

1
2
3
4
"" + 1 + 2; // "12"
"" + ( 1 + 2 ); // "3"
"" + 0.0000001; // "1e-7"
parseInt( 0.0000001 ); // 1 (!)

或者您可以使用JavaScript所提供的String类, 尝试将其解析一个值字符串:

1
2
String( 1 ) + String( 2 ); // "12"
String( 1 + 2 ); // "3"

NaN 和 Infinity(无穷)

解析一些东西的时候,如果解析结果不是一个数字,那么结果为NaN。 可以使用isNaN来检测这些情况:

1
2
parseInt( "hello", 10 ) // NaN
isNaN( parseInt("hello", 10) ) // true

被零除的结果为Infinity:

1
1 / 0 // Infinity

NaN的和Infinity的类型都是"number":

1
2
typeof NaN // "number"
typeof Infinity // "number"

需要注意的是NaN比较是个奇葩:

1
NaN == NaN // false (!)

但是:

1
Infinity == Infinity // true

整数

一个整数,是一个普通的数字型, 但每当在API文档中明确提到,表明非浮点数的预期。

Float

一个浮点数,是一个普通的数字型,就像整型一样,每当在API文档中明确提到,表明是一个浮点数的预期。


Boolean

A boolean in JavaScript can be either true or false:

1
2
if ( true ) console.log( "always!" );
if ( false ) console.log( "never!" );

Object

Everything in JavaScript is an object, though some are more objective (haha). The easiest way to create an object is the object literal:

1
2
3
4
5
var x = {};
var y = {
name: "Pete",
age: 15
};

The type of an object is "object":

1
typeof {} // "object"

Dot Notation

You can write and read properties of an object using the dot notation:

1
2
3
4
y.name // "Pete"
y.age // 15
x.name = y.name + " Pan" // "Pete Pan"
x.age = y.age + 1 // 16

Array Notation

Or you write and read properties using the array notation, which allows you to dynamically choose the property:

1
2
3
4
5
6
7
var operations = {
increase: "++",
decrease: "--"
};
var operation = "increase";
operations[ operation ] // "++"
operations[ "multiply" ] = "*"; // "*"

Iteration

Iterating over objects is easy with the for-in-loop:

1
2
3
4
5
6
7
var obj = {
name: "Pete",
age: 15
};
for( key in obj ) {
alert( "key is " + [ key ] + ", value is " + obj[ key ] );
}

Note that for-in-loop can be spoiled by extending Object.prototype (see Object.prototype is verboten) so take care when using other libraries.

jQuery provides a generic each function to iterate over properties of objects, as well as elements of arrays:

1
2
3
jQuery.each( obj, function( key, value ) {
console.log( "key", key, "value", value );
});

The drawback is that the callback is called in the context of each value and you therefore lose the context of your own object if applicable. More on this below at Functions.

Boolean default

An object, no matter if it has properties or not, never defaults to false:

1
2
!{} // false
!!{} // true

Prototype

All objects have a prototype property. Whenever the interpreter looks for a property, it also checks in the object's prototype if the property is not found on the object itself. jQuery uses the prototype extensively to add methods to jQuery instances. Internally, jQuery makes jQuery.fn an alias of jQuery.prototype so you can use either one (though plugin developers have standardized on fn).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var form = $("#myform");
console.log( form.clearForm ); // undefined
// jQuery.fn == jQuery.prototype
jQuery.fn.clearForm = function() {
return this.find( ":input" ).each(function() {
this.value = "";
}).end();
};
// works for all instances of jQuery objects, because
// the new method was added to the prototype
console.log( form.clearForm ); // function
form.clearForm();

Array

Arrays in JavaScript are mutable lists with a few built-in methods. You can define arrays using the array literal:

1
2
var x = [];
var y = [ 1, 2, 3 ];

The type of an array is "object":

1
2
typeof []; // "object"
typeof [ 1, 2, 3 ]; // "object"

Reading and writing elements to an array uses the array-notation:

1
2
x[ 0 ] = 1;
y[ 2 ] // 3

Iteration

An array has a length property that is useful for iteration:

1
2
3
for ( var i = 0; i < a.length; i++ ) {
// Do something with a[i]
}

When performance is critical, reading the length property only once can help to speed things up. This should be used only when a performance bottleneck was discovered:

1
2
3
for ( var i = 0, j = a.length; i < j; i++ ) {
// Do something with a[i]
}

Another variation defines a variable that is filled for each iteration, removing the array-notation from the loop-body. It does not work when the array contains 0 or empty strings!

1
2
3
for ( var i = 0, item; item = a[i]; i++ ) {
// Do something with item
}

jQuery provides a generic each function to iterate over element of arrays, as well as properties of objects:

1
2
3
4
var x = [ 1, 2, 3 ];
jQuery.each( x, function( index, value ) {
console.log( "index", index, "value", value );
});

The drawback is that the callback is called in the context of each value and you therefore lose the context of your own object if applicable. More on this below at Functions.

The length property can also be used to add elements to the end of an array. That is equivalent to using the push-method:

1
2
3
4
var x = [];
x.push( 1 );
x[ x.length ] = 2;
x // [ 1, 2 ]

You'll see both variations a lot when looking through JavaScript library code.

Other built-in methods are reverse, join, shift, unshift, pop, slice, splice and sort:

1
2
3
4
5
6
7
8
var x = [ 0, 3, 1, 2 ];
x.reverse() // [ 2, 1, 3, 0 ]
x.join(" – ") // "2 - 1 - 3 - 0"
x.pop() // [ 2, 1, 3 ]
x.unshift( -1 ) // [ -1, 2, 1, 3 ]
x.shift() // [ 2, 1, 3 ]
x.sort() // [ 1, 2, 3 ]
x.splice( 1, 2 ) // [ 2, 3 ]

Note: .unshift() method does not return a length property in Internet Explorer.

Boolean Default

An array, no matter if it has elements or not, never defaults to false:

1
2
![] // false
!![] // true

Array<Type> Notation

In the jQuery API you'll often find the notation of Array<Type>:

dragPrevention    Array<String>
    

This indicates that the method doesn't only expect an array as the argument, but also specifies the expected type. The notation is borrowed from Java 5's generics notation (or C++ templates).

PlainObject

The PlainObject type is a JavaScript object containing zero or more key-value pairs. The plain object is, in other words, an Object object. It is designated "plain" in jQuery documentation to distinguish it from other kinds of JavaScript objects: for example, null, user-defined arrays, and host objects such as document, all of which have a typeof value of "object." The jQuery.isPlainObject() method identifies whether the passed argument is a plain object or not, as demonstrated below:

1
2
3
4
5
6
7
8
9
10
11
var a = [];
var d = document;
var o = {};
typeof a; // object
typeof d; // object
typeof o; // object
jQuery.isPlainObject( a ); // false
jQuery.isPlainObject( d ); // false
jQuery.isPlainObject( o ); // true

Date

The Date type is a JavaScript object that represents a single moment in time. Date objects are instantiated using their constructor function, which by default creates an object that represents the current date and time.

1
new Date();

To create a Date object for an alternative date and time, pass numeric arguments in the following order: year, month, day, minute, second, millisecond — although note that the month is zero-based, whereas the other arguments are one-based. The following creates a Date object representing January 1st, 2014, at 8:15.

1
new Date( 2014, 0, 1, 8, 15 );

Function

A function in JavaScript can be either named or anonymous. Any function can be assigned to a variable or passed to a method, but passing member functions this way can cause them to be called in the context of another object (i.e. with a different "this" object).

1
2
function named() {}
var handler = function() {}

You see a lot of anonymous functions in jQuery code:

1
2
3
4
5
6
$( document ).ready(function() {});
$( "a" ).click(function() {});
$.ajax({
url: "someurl.php",
success: function() {}
});

The type of a function is "function".

Arguments

Inside a function a special variable "arguments" is always available. It's similar to an array in that it has a length property, but it lacks the built-in methods of an array. The elements of the pseudo-array are the argument of the function call.

1
2
3
4
5
6
function log( x ) {
console.log( typeof x, arguments.length );
}
log(); // "undefined", 0
log( 1 ); // "number", 1
log( "1", "2", "3" ); // "string", 3

The arguments object also has a callee property, which refers to the function you're inside of. For instance:

1
2
var awesome = function() { return arguments.callee; }
awesome() == awesome // true

Context, Call and Apply

In JavaScript, the variable "this" always refers to the current context. By default, "this" refers to the window object. Within a function this context can change, depending on how the function is called.

All event handlers in jQuery are called with the handling element as the context.

1
2
3
4
5
6
$( document ).ready(function() {
// this refers to window.document
});
$( "a" ).click(function() {
// this refers to an anchor DOM element
});

You can specify the context for a function call using the function-built-in methods call and apply. The difference between them is how they pass arguments. Call passes all arguments through as arguments to the function, while apply accepts an array as the arguments.

1
2
3
4
5
6
function scope() {
console.log( this, arguments.length );
}
scope() // window, 0
scope.call( "foobar", [ 1, 2 ] ); // "foobar", 1
scope.apply( "foobar", [ 1, 2 ] ); // "foobar", 2

Scope

In JavaScript, all variables defined inside a function are only visible inside that function scope. Consider the following example:

1
2
3
4
5
6
7
8
// global
var x = 0;
(function() {
// private
var x = 1;
console.log( x ); // 1
})();
console.log( x ); // 0

It defines a variable x in the global scope, then defines an anonymous function and executes it immediately (the additional parentheses are required for immediate execution). Inside the function another variable x is defined with a different value. It is only visible within that function and doesn't overwrite the global variable.

Closures

Closures are created whenever a variable that is defined outside the current scope is accessed from within some inner scope. In the following example, the variable counter is visible within the create, increment, and print functions, but not outside of them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function create() {
var counter = 0;
return {
increment: function() {
counter++;
},
print: function() {
console.log( counter );
}
}
}
var c = create();
c.increment();
c.print(); // 1

The pattern allows you to create objects with methods that operate on data that isn't visible to the outside—the very basis of object-oriented programming.

Proxy Pattern

Combining the above knowledge gives you as a JavaScript developer quite a lot of power. One way to combine that is to implement a proxy pattern in JavaScript, enabling the basics of aspect-oriented programming (AOP):

1
2
3
4
5
6
7
8
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();

The above wraps its code in a function to hide the "proxied"-variable. It saves jQuery's setArray-method in a closure and overwrites it. The proxy then logs all calls to the method and delegates the call to the original. Using apply(this, arguments) guarantees that the caller won't be able to notice the difference between the original and the proxied method.

Callback

A callback is a plain JavaScript function passed to some method as an argument or option. Some callbacks are just events, called to give the user a chance to react when a certain state is triggered. jQuery's event system uses such callbacks everywhere:

1
2
3
$( "body" ).click(function( event ) {
console.log( "clicked: " + event.target );
});

Most callbacks provide arguments and a context. In the event-handler example, the callback is called with one argument, an Event. The context is set to the handling element, in the above example, document.body.

Some callbacks are required to return something, others make that return value optional. To prevent a form submission, a submit event handler can return false:

1
2
3
$( "#myform" ).submit(function() {
return false;
});

Instead of always returning false, the callback could check fields of the form for validity, and return false only when the form is invalid.


Selector

A selector is used in jQuery to select DOM elements from a DOM document. That document is, in most cases, the DOM document present in all browsers, but can also be an XML document received via Ajax.

The selectors are a composition of CSS and custom additions. All selectors available in jQuery are documented on the Selectors API page.

There are lot of plugins that leverage jQuery's selectors in other ways. The validation plugin accepts a selector to specify a dependency, whether an input is required or not:

1
2
3
emailrules: {
required: "#email:filled"
}

This would make a checkbox with name "emailrules" required only if the user entered an email address in the email field, selected via its id, filtered via a custom selector ":filled" that the validation plugin provides.

If Selector is specified as the type of an argument, it accepts everything that the jQuery constructor accepts, eg. Strings, Elements, Lists of Elements.

Event

jQuery's event system normalizes the event object according to W3C standards. The event object is guaranteed to be passed to the event handler (no checks for window.event required). It normalizes the target, relatedTarget, which, metaKey and pageX/Y properties and provides both stopPropagation() and preventDefault() methods.

Those properties are all documented, and accompanied by examples, on the Event object page.

The standard events in the Document Object Model are: blur, focus, load, resize, scroll, unload, beforeunload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, and keyup. Since the DOM event names have predefined meanings for some elements, using them for other purposes is not recommended. jQuery's event model can trigger an event by any name on an element, and it is propagated up the DOM tree to which that element belongs, if any.

Element

An element in the Document Object Model (DOM) has attributes, text and children. It provides methods to traverse the parent and children and to get access to its attributes. Due to a lot of flaws in DOM API specifications and implementations, those methods are no fun to use. jQuery provides a wrapper around those elements to help interacting with the DOM. But often enough you will be working directly with DOM elements, or see methods that (also) accept DOM elements as arguments.

Whenever you use jQuery's each-method, the context of your callback is set to a DOM element. That is also the case for event handlers.

Some properties of DOM elements are quite consistent among browsers. Consider this example of a simple on-blur-validation:

1
2
3
4
5
$( ":text" ).blur(function() {
if( !this.value ) {
alert( "Please enter some text!" );
}
});

You could replace this.value with $(this).val() to access the value of the text input via jQuery, but in that case you don't gain anything.

jQuery

A jQuery object contains a collection of Document Object Model (DOM) elements that have been created from an HTML string or selected from a document. Since jQuery methods often use CSS selectors to match elements from a document, the set of elements in a jQuery object is often called a set of "matched elements" or "selected elements".

The jQuery object itself behaves much like an array; it has a length property and the elements in the object can be accessed by their numeric indices [0] to [length-1]. Note that a jQuery object is not actually a Javascript Array object, so it does not have all the methods of a true Array object such as join().

Most frequently, you will use the jQuery() function to create a jQuery object. jQuery() can also be accessed by its familiar single-character alias of $(), unless you have called jQuery.noConflict() to disable this option. Many jQuery methods return the jQuery object itself, so that method calls can be chained:

In API calls that return jQuery, the value returned will be the original jQuery object unless otherwise documented by that API. API methods such as .filter() or .not() modify their incoming set and thus return a new jQuery object.

1
$( "p" ).css( "color", "red" ).find( ".special" ).css( "color", "green" );

Whenever you use a "destructive" jQuery method that potentially changes the set of elements in the jQuery object, such as .filter() or .find(), that method actually returns a new jQuery object with the resulting elements. To return to the previous jQuery object, you use the .end() method.

A jQuery object may be empty, containing no DOM elements. You can create an empty jQuery object with $() (that is, passing no arguments at all). A jQuery object may also be empty if a selector doesn't select any elements, or if a chained method filters out all the elements. It is not an error; any further methods called on that jQuery object simply have no effect since they have no elements to act upon. So, in this example if there are no bad entries on the page then no elements will be colored red:

1
$( ".badEntry" ).css({ color: "red" });

XMLHttpRequest

Some of jQuery's Ajax functions return the native XMLHttpRequest (XHR) object, or pass it as an argument to success/error/complete handlers, so that you can do additional processing or monitoring on the request. Note that Ajax functions only return or pass an XHR object when an XHR object is actually used in the request. For example, JSONP requests and cross-domain GET requests use a script element rather than an XHR object.

Although the XHR object is a standard, there are variations in its behavior on different browsers. Refer to the W3C site and browsers' documentation for more information:

Google does not appear to have an official page for their XHR documentation for Chrome. As of version 5, Chrome does not support the use of the file protocol for XHR requests.

jqXHR

As of jQuery 1.5, the $.ajax() method returns the jqXHR object, which is a superset of the XMLHTTPRequest object. For more information, see the jqXHR section of the $.ajax entry

Deferred Object

As of jQuery 1.5, the Deferred object provides a way to register multiple callbacks into self-managed callback queues, invoke callback queues as appropriate, and relay the success or failure state of any synchronous or asynchronous function.

Promise Object

This object provides a subset of the methods of the Deferred object (then, done, fail, always, pipe, and state) to prevent users from changing the state of the Deferred.

Callbacks Object

A multi-purpose object that provides a powerful way to manage callback lists. It supports adding, removing, firing, and disabling callbacks. The Callbacks object is created and returned by the $.Callbacks function and subsequently returned by most of that function's methods.

XML Document

A document object created by the browser's XML DOM parser, usually from a string representing XML. XML documents have different semantics than HTML documents, but most of the traversing and manipulation methods provided by jQuery will work with them.