Douglas Crockford - The JavaScript Programming Language
Numbers
Strings
Booleans
Objects
null
undefined
Numbers
• Only one number type
○ No integers
• 64-bit floating point
• IEEE-754 aka “Double”
• Does not map well to common understanding of arithmetic:
• 0.1 + 0.2 = 0.30000000000000004
NaN
Numbers type
• Special number: Not a Number
• Result of undefined or erroneous operations
• Toxic: any arithmetic operation with NaN as an input will have NaN as a result
• NaN is not equal to anything, including NaN.
Number function
Number(value)
• Converts the value into a number.
• It produces NaN if it has a problem.
• Similar to + prefix operator.
parseInt function
parseInt(value, 10)
· Converts the value into a number.
· It stops at the first non-digit character.
· The radix(10) should be required.
Math
· Math object is modelled on Java’s Math class.
· It contains
abs absolute value
floor Integer
Math.floor(number) - gets the integer part.
log logarithm
max maximum
pow raise to a power
random random number
round nearest integer
sin sine
sqrt square root
Strings
• Sequence of 0 or more 16-bit characters
○ UCS-2, not quite UTF-16
○ No awareness of surrogate pairs
• No separate character type
○ Characters are represented as strings with a length of 1
• Strings are immutable
cant be modify after created.
• Similar strings are equal (==)
• String literals can use single or double quotes
String length
• `string.length`
• The `length` property determines the number of 16-bit characters in a string.
String function
String(value)
• Converts value to a string
String Methods
• chatAt
• concat
• indexOf
• lastIndexOf
• match
• replace
• search
• slice
• split
• substring
• toLowerCase
• toUpperCase
Boolean
• true
• false
Boolean function
Boolean(value)
• Returns true if value is truthy
• Returns false if value is falsy
• Similar to !! Prefix operator
null
• A value that isn't anything
undefined
• A value that isn't even that.
• The default value for variables and parameters
• The value of missing members in objects
Falsy values
false
null
undefined
“”
0
NaN
All other values (including all objects) are truthy.
e.g. “0” “False”
Everything Else Is Objects
JavaScript is all about objects!
Dynamic Objects
• Unification of Object and Hashtable
• new Object() produces an empty container of name/value pairs
• A name can be any string, a value can be any value except undefined
• members can be accessed with dot notation or subscript notation
<!--0-->
• No hash nature is visible (no hash codes or rehash methods)
Loosely Typed
• Any of these types can be stored in an variable, or passed as a parameter to any function.
• The language is not "untyped"
C
• JavaScript is syntactically a C family language
• It differs from C mainly in its type system, which allows functions to be values.
Identifiers
• Starts with a letter or _ or $
• Followed by zero or more letters, digits, _ or $
• By convention, all variables, parameters, members, and function names start with lower case
• Except for **constructors which start with upper case**
• Initial _ should be reserved for implementations
• $ should be reserved for machines. (microprocessors & program generators)
Reserved Words
abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function
goto
if implements import in instanceof int
interface
long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
Comments
// slashslash line comment
/
slashstar
block
Comment
/
Operators
• Arithmetic
+ - * / %
• Comparison
== != < > <= >=
• Logical
&& || !
• Bitwise
& | ^ >> >>> <<
• Ternary
?:
+
• Addiction and concatenation
• If both operands are number,
then
add them
else
convert them both to strings
concatenate them
'$' + 3 + 4 = '$34'
+
• Unary operator can convert strings to numbers
+"42" = 42
• Also
Number("42") = 42
• Also
parseInt("42", 10) = 42
**+"3" + (+"4") = 7**
/
Division of two integers can produce a non-integer result
10 / 3 = 3.333333333333333
== !=
• Equal and not equal
• These operators can do type coercion
• It is better to use === and !==,
which do not do type coercion.
&&
• The guard operator, aka logical and
• If first operand is truthy
**Then result is second operand**
**Else result is first operand**
• It can be used to avoid null references
<!--1-->
• can be written as
<!--2-->
||
• The default operator, aka logical or
• If first operand is truthy
*Then result is first operand
*Else result is second operand
• It can be used to fill in default values.
<!--3-->
• If input is truthy, then last is input, otherwise set last to nr_items.
!
• Prefix logical not operator.
• If the operand is truthy, the result is false. Otherwise, the result is true.
• !! Produces booleans.
Bitwise
& | ^ >> >>> <<
The bitwise operators convert the operand to a 32-bit signed integer, and turn the result back into 64-bit floating point.
Statements
expression
if
switch
while
do
for
break
continue
return
try/throw
Break statement
• Statements can have labels.
• Break statements can refer to those labels.
loop: for (;;) { |
For statement
Iterate through all of the elements of an array;
For (var I = 0;I < array.length; I += 1) { |
Iterate through all of the members of an object:
for (var name in object) { |
Switch statement
*Multiway branch
*The switch value does not need to be a number. It can be a string.
*The case values can be expressions.
Switch statement
swith (expression) { |
Throw statement
throw new Error(reason); |
Try statement
try { |
Try Statement
- The JavaScript implementation can produce these exception names:
‘Error’
‘EvalError’
‘RangeError’
‘SyntaxError’
‘TypeError’
‘URIError’
With statement
Intended as a short-hand
Ambiguous
Error-prone
Don’t use it
with (o) { |
Function statement
function name(parmeters) { |
Var statement
- Defines variables within a function.
- Types are not specified.
- Initial values are optional.
var name; |
Scope
- In JavaScript, {block} do not have scope.
- Only functions have scope.
- Vars defined in a function are not visible outside of the function.
Declare variable any place inside of a function, it’s visible anywhere inside of the function.
Declare variable twice inside of a function, it only gets created once!
Global Variables
JavaScript has implied Globals.
If you create a variable and forget to declare it, JavaScript assumes you might the variable to be global variable.
For example if you forget to define i
, you create a global variable called i
.
If you make the same mistake in two places, there is a good chance your program is going to be failed.
Return statement
return expression; |
or
return; |
In JavaScript, every function will return a result, no void type in js.
- If there is no expression, then the return value is undefined.
- Except for constructors, whose default return value is this. It returns the new object.
Objects
- Everything else is objects.
- Objects can contain data and methods.
- Objects can inherit from other objects.
Objects are collections
Collections
*An object is an unordered collection of name/value pairs
*Names are strings
*Values are any type, including other objects
*Good for representing records and trees.
*Every object is a little database.
Object Literals
- Object literals are wrapped in { }
- Names can be names or strings
- Values can be expressions
- : separates names and values
- , separates pairs
- Object literals can be used anywhere a value can appear.
var myObject = { |
Maker function
function maker(name, where, grade, level) { |
Object Literals
var myObject = { |
Object Literals
myFunction({ |
throw { |
Object Literals
function SuperDiv(width, height, left, top, zIndex, position, color, |
Object Augmentation (n. 扩大; 增大; 增加物; <音>主题延长)
New members can be added to any object by simple assignment
There is no need to define a new class
var myObject = { |
Linkage
Objects can be created with a secret link to another object. (Inheritance)
Objects are able to be inheritanced from other objects.
If an attempt to access a member from an object which fails, the secret linked object will be used.
The secret link is not used when storing. New members are only added to the primary object.
The object(o) function makes a new empty object with a linkage to object o.
Linkage
var myOldObject = { |
myNewObject.name = "Tom Piperson"; |
Inheritance
- Linkage provides simple Inheritance.
- An object can inherit from an old object.
Prototypal Inheritance
Some languages have classes, methods, constructors, and modules.
JavaScript’s functions do the work of all of those.Instead of Classical Inheritance,
JavaScript has Prototypal Inheritance.It accomplishes the same things, but differently.
It offers greater expressive power.
But it’s different.
Prototypal Inheritance
Instead of organizing objects into rigid classes, new objects can be made that are similar to existing objects, and then customized.
Object customization is a lot less work than making a class, and less overhead, too.
One of the keys is the object(o) function.
The other key is functions.
myOldObject.grade = "B"; |
Single Inheritance (long linkage)
Garbage Collection
Q&A
What happened to the new objects if the old object set to undefined?
Nothing!
Object Methods
- All objects are linked directly or indirectly to Object.prototype.
Object.prototype provides system built-in methods for you. All objects inherit some basic methods.
None of them are very userful.
hasOwnProperty(name)
Is the name a true member of this object?No copy method.
No equals methos.
Can use equal operator to check two references to the same object, but it doesnt tell you two object contains the same staff.
Object Construction
Make a new empty object
Three ways to make new empty object!
All three of these expressions have exactly the same result:
new Object() |
- {} is the preferred form.
Reference
Objects can be passed as arguments to functions, and can be returned by functions
Objects are passed by reference.
Objects are not passed by value.The === operator compares object references, not values
true only if both operands are the same object.
Delete
- Members can be removed from an object with the delete operator.
delete myObject[name];
change the value to undefined.
Arrays
Array inherits from Object.
Indexes are converted to strings and used as names from retrieving values.
Very efficient for sparse arrays. (创建稀疏矩阵)
Not very efficient in most other cases.
One advantage: No need to provide a length or type when creating an array.
length
Arrays, unliket objects, have a special
length
member.It is always 1 larger than the highest integer subscript.
It allows use of the traditaional for statement.
for (i = 0; i< a.length; i+= 1) {
...
}Do not use for .. in with arrays.
Array Literals
An array literal uses []
It can contain any number of expressions, separated by commas
myList = ['oats', 'peas', 'beans'];
New items can be appended
myList[myList.length] = 'barley';
The dot notation should not be used with arrays.
[] is preferred to new Array().
Array Methods
- concat
- join
- pop
- push
- slice
- sort
- splice
Deleting Elements
delete array[number]
- Removes the element, but leaves a hole in the numbering.
array.splice(number, 1); |
- Removes the element and renumbers all the following elements.
Deleting Elements
myArray = ['a', 'b', 'c', 'd']; |
Arrays v Objects
Use objects when the names are arbitrary strings.
Use arrays when the names are sequential integers.
Don’t get confused by the term Associative Array.
Array has secret link which links to Array.prototype
.
Distinguishing Arrays
value.constructor === Array |
Neither of these work when the value comes from a different frame. (talk later!)
We cant inherited from an array effectivly. We cant use array as a prototype.
Arrays and Inheritance
- Don’t use arrays as prototypes.
var array = [1];
var notArray = Object(array);
The thing got produced by Object(array)
is an object instead of an array.
The object produced this way does not have array nature. It will inherit the array’s values and methods. but not its length.
- You can augment an individual array.
By assigning methods to it since it is underneath an object it’s able to receive any kind of value including functions in any kind of key not just numbers.
This works because arrays are objects.
Since it’s underneath an object, it’s able to receive any kind of values including functions and any kind of keys not just numbers.
- You can augment all arrays.
Assign methods to Array.prototype.
Functions
- Functions are first class objects.
Functions can be passed, returned, and stored just like any other value.
Functions inherit from
Object
and can store name/value pairs.
Function operator
- The function operator takes an optional name, a parameter list, and a block of statements, and returns a function object.
function name(parameters) { |
- A function can appear anywhere that an expression can appear.
Lambda
What JavaScript calls
function
, other languages calllambda
.It is a source of enormous expressive power.
Unlike most power-constructs, it is secure.
Function statement
The function statement is just a short-hand for a var
statement with a function value.
function foo() {}
expands to
var foo = function foo() {};
There is one namespace for both of those things.
Inner functions
Functions do not all have to be defined at the top level (or left edge).
Functions can be defined inside of other functions.
Scope
An inner function has access to the variables and parameters of functions that it is contained within.
This is known as Static Scoping or Lexical Scoping.
Closure
The
scope
that an inner function enjoys continues even after the parent functions have returned.This is called
closure
.
function fade(id) { |
Function Objects
Functions are objects, so they can contain name/value pairs.
This can serve the same purpose as
static
members in other languages.
Methods
Since functions are values, functions can be stored in objects.
A function in an object is called a method.
var foo = function () {};
Invocation
If a function is called with too many arguments, the extra arguments are ignored.
If a function is called with too few arguments, the missing values will be
undefined
.There is no implicit type checking on the arguments.
Invocation
- There are four ways to call a function:
Method form
thisObject.methodName(arguments)
thisObject["methodName"](arguments)
Function form
functionObject(arguments)
Constructor form
new functionObject(arguments)
Apply form
functionObject.apply(thisObject, [arguments])
Method form
thisObject.methodName(arguments)
- When a function is called in this form, In additional its regular parameters, it gets a special extra parameter called ‘this’.
And ‘this’ will be bind to ‘thisObject’.
So it gives that function access to the object that it was invoked in.
When a function is called in the method form, this
is set to thisObject
, the object containing the function.
- This allows methods to have a reference to the object of interest.
Function form
functionObject(arguments)
When a function is called in the function form, this
is set to the global object.
That is not very useful.
Mistake or not? It makes it harder to write helper functions within a method because the helper function does not get access to the outer this
.
var that = this;
Constructor form
new functionObject(arguments)
When a function is called with the
new
operator, a new object is created and assigned tothis
.If there is not an explicit return value, then
this
will be returned.
this
this
is an extra parameter. Its value depends on the calling form.this
gives methods access to their objects.this
is bound at invocation time.
Invocation form | this |
---|---|
function | the global object |
method | the object |
constructor | the new object |
arguments
When a function is invoked, in addition to its parameters, it also gets a special parameter called
arguments
.It contains all of the arguments from the invocation.
It is an array-like object.
arguments.length
is the number of arguments passed.
Example
function sum() { |
Augmenting Build-in Types
- Object.prototype
- Array.prototype
- Function.prototype
- Number.prototype
- String.prototype
- Boolean.prototype
trim
String.prototype.trim = function () { |
supplant
var template = '<table border="{border}">' + |
typeof
The typeof prefix operator returns a string identifying the type of a value.
type | typeof |
---|---|
object | ‘object’ |
function | ‘function’ |
array | ‘object’ |
number | ‘number’ |
string | ‘string’ |
boolean | ‘boolean’ |
null | ‘object’ |
undefined | ‘undefined’ |
eval
eval(string)
calling compiler to do something
The
eval
function compiles and executes a string (in the context of the function that is callingeval
) and returns the result.It is what the browser uses to convert strings into actions.
It is the most misused feature of the language.
Recommend that not use it ever!
- Waste lot of time. Often you calling the compiler to do something which can be done much easier on that.
- People dont know how to use subscript notation. They will concated dot notation then eval them. The slowest way to doing this.
- For certain of checking done in running time it could’ve been done to compile time. Delays error detection, makes it easier to ship bugs.
- Security problem.
Using eval on Json is the only time when its correct to use eval.
Use parseJson
method!
new Function function
new Function(parameters, body)
when a script tag or an eventhandler on the page,
brower call ‘eval’ to do with it.
eval
calls thenew Function(parameters, body)
.
TheFunction
constructor takes zero or more parameter name strings, and a body string, and uses the JavaScript compiler to produce a function object.It should only be used to compile fresh source from a server.
It it closely related to
eval
.
Build-int Type Wrappers
Java has both
int
andInteger
type, one is an simple value and the other is an object which wraps the simple value.
Two incompatible types which can both carry the same value with differing levels of efficiency and convenience.JavaScript copied this pattern to no advantage. Avoid it.
- Avoid
new Boolean()
- Avoid
new String()
- Avoid
new Number()
Confession
function object(o) { |
Augmentation
*We can directly modify individual objects to give them just the characteristics we want.
*We can do this without having to create classes.
*We can then use our new object as the prototype for lots of new objects,
each of which can also be augmented.
Working with the Grain
Classical patterns are less effective than prototypal patterns or parasitic patterns(talk in the advanced classes) .
Formal classes are not needed for reuse or extension.
(global) Object
The object that dares not speak its name.
It is the container for all global variables and all built-in objects.
Sometimes
this
points to it.var global = this;
On browsers,
window
is the globalobject
.- On nodejs,
global
is the globalobject
.
They assigned to the global object a window member whose value is global object.
global.window = global; |
window.something -> global object -> window
Instead of a linker, everything has been reslove in a global namespace
that namespace is the global object, and it is implemented as a JavaScript object.
Global variables are evil
Functions within an application can clobber each other.
Cooperating applications can clobber each other.
Use of the global namespace must be minimized.
Implied Global
Any var which is not properly declared is assumed to be global by default.
This makes it easy for people who do not know or care about encapsulation to be productive, but it makes applications less reliable.
JSLint is a tool which helps identify implied globals and other weaknesses.
http://www.JSLint.com
Namespace
Every object is (on its own namespace) a separate namespace.
Use an object to organize your variables and functions.
The YAHOO Object.<head>
<script>
YAHOO={};
</script>
</head>
Encapsulate
Function scope can create an encapsulation
Use an anonymous function to wrap your application.(talk about in advanced classes)
Example
YAHOO.Trivia = function () { |
Thinking about type
Trading type-safety for dynamism(n.(人的)活力; 精力,魄力; 劲头;).
JavaScript has no cast operator.
Reflection is really easy, and usually unnecessary.
Why inheritance?
Automatic casting
Code reuseTrading brittleness (n.脆性,脆度,脆弱性) for flexibility
Date
The Date
function is based on Java’s Date class.
It was not Y2K ready.
RegExp
- Regular expression pattern matcher
- Patterns are enclosed in slashes
- Example: a pattern that matches regular expressions
/\/(\[^\x00-\xlf]|[(\[^\x00-\xlf]|[^\x00-\xlf\\/])]|[^\x00-\xlf\\/[])+\/[gim]/
- Bizarre notation, difficult to read
Threads
The language definition is neutral on threads.
Some language processors (like SpiderMonkey) provide thread support
Most application environments (like browsers) do not provide it
Threads are evil
Platforms
Browsers
Windows Script Host and Dashboard
Yahoo!Widgets
DreamWeaver and Photoshop
Embedded
ActionScript
- Empty strings are truthy
- keywords are case insensitive
- No Unicode support
- No
RegExp
- No
try
- No statement labels
||
and&&
return booleans- separate operators for strings and numbers
E4X
- Extensions to ECMAScript for XML
- Proposed by BEA
- Allows
literals - Not compatible with ECMAScript Third Edition
- Not widly accepted yet
- Not in IE7
Style
- Progamming style isnt about personal taste.
- It is about rigor in expression.
- It is about clearness in presentation.
- It is about product adaptability and longevity.
- Good rules help us to keep the quality of our programs high.
Style and JavaScript
Style is critically important for JavaScript.
The dynamic nature of the language is considered by some to be “too soft”.
Discipline is necessary for balance.Most of the world’s body of JavaScript programs is crap.
Code Conventions for the JavaScript Programming Language
http://JavaScript.crockford.com/code.html
Semicolon insertion
- When the compiler sees an error, it attempts to replace an nearby linefeed(n.换行) with a semicolon and try again.
- This should alarm you.
- It can mask errors.
- Always use the full, correct forms, including semicolons.
Line Ending
Break a line after a punctuator:
,.;:{} ([=<>?!+-/%~^|&==!=<=>+=-==/=%=^=|=&=<<>>||&&===!==<<= >>= >>> >>>=
Do not break after a name, string, number, or ) ] ++ —
Defense against copy/paste errors.
Comma
Avoid tricky expressions using the comma operators.tags: JavaScript
Do not use extra commas in array literals.
Good: [1, 2, 3]
- Bad: [1, 2, 3,]
Required Blocks
Good:
if (a) {
b();
}Bad:
if (a) b();
Forbidden Blocks
Blocks do not have scope in JavaScript
Blocks should only be used with structured statementsfunction
if
switch
while
for
do
try
Variables
Define all variables at the beginning of the function.
JavaScript does not have block scope, so their is no advantage in declaring variables at the place of their first use.
Expression Statements
Any expression can be used as a statement. That can mask errors.
Only assignement expressions and invocation expressions should be used as statements.
Good:
foo();
Bad:
foo && foo();
switch Statement
Avoid using
fallthrough.
Each clause should explicitly break
or return
or throw
.
Assignment Expressions
Do not use assignment expressions in the condition parts of if
, while
, or for
.
It is more likely thatif (a = b) { ... }
was intended to beif (a == b) { ... }
Avoid tricky expressions.
== and !=
Be aware that == and != do type coercion.
Badif (a == null) { ... }
Good:if (a === null) { ... }
if (!a) { ... }
Labels
Use labels only on these statements:do
for
switch
while
- Never use
JavaScript:
as a label.