An expression is a phrase in javascript, and the javascript interpreter will calculate a result. Commonly used quantities in programs are the simplest type of expressions, which are variables. Variable names are also a simple expression, and their value is the value assigned to the variable.
Complex expressions are composed of simple expressions. For example, an array access expression is composed of an expression representing an array, square brackets, and an integer expression. The new expression operation they form is the element value at a specific position in the array. Same letter
A number call expression consists of an expression representing a function object and 0 more than 0 parameter expressions. The most common method of combining simple expressions into complex expressions is operators.
This chapter (this article) will explain all javascript operators. It also explains expressions that do not involve operators (such as accessing array elements and function calls), and their syntax and programming style are very similar to those of C language.
1. Element expression
The simplest expression is "original expression", which is the smallest unit of an expression - they do not contain other expressions. Original expressions in javascript contain constants or direct quantities. Keywords and variables.
A direct quantity is a constant value that appears directly in the program. They look like:
The code copy is as follows:
1.23 //Direct quantity
"hello" //Stand direct quantity
/pattern/ // Regular expression direct quantity
Some reserved words in javascript form the original expression
The code copy is as follows:
true //Boolean value: true
false //False
null //Return a value: empty
this //Return the "current" object
Through the learning of Chapter 3, unlike other keywords, this is not a constant, and the values it returns in different parts of the program are also different. This keyword often appears in object-oriented programming. This returns the object of the square method.
Finally, the third original expression is a variable
The code copy is as follows:
i //Return the value of variable i
sum //Return the sum value
undefined // is a global variable, unlike null, it is not a keyword
2. Initialization expressions of objects and arrays.
Object and array initialization is actually newly created objects and arrays. These initialized expressions are sometimes called "object direct quantity" and "array direct quantity". However, unlike Boolean direct quantities, they are not original expressions because the members or elements they contain are subexpressions.
The syntax of the initialization expression of an array is very simple, let's start below
The initialization expression of an array is composed of a pair of square brackets and a comma-separated list. The initialization result is a newly created array. Elements of an array are comma-separated values of expressions.
[] // An empty array; [] Leave empty in it means that the array has no elements
[1+2,3+4] //Array with two elements, the first one is 3, the second one is 7
The element initialization expression in an array initialization expression can be an array initialization expression. That is to say, expressions can be nested
The code copy is as follows:
var mat = [[1,2,3],[4,5,6],[7,8,9]];
Elements between lists in the array can be omitted, and the space will be filled with undefined. For example:
The code copy is as follows:
var a=[1,,,,5]
Four of the elements are undefined. A comma is left at the end of the direct quantity of the array, and a new element with an undefined value will not be created.
Object initialization expressions are very similar to array initialization expressions, except that square brackets are replaced by curly brackets. And each word expression contains an attribute name and a non-colon as prefix.
The code copy is as follows:
var p = {x: 2.1,y: -3} // An object with two attribute members
var q = {}; //Empty object
qx=2.1;qy=-3; //The attribute members of q are the same as those of p
The object can also be nested directly, for example
The code copy is as follows:
var anh = {left:{x:2,y:3},
right:{x:4,y:5}}
When javascript calculates the value of an object initialization expression, the object expressions are calculated each time, and they do not have to include constant values: they can be any javascript expression. Similarly, the name of the property in the object's direct quantity can be a string instead of an identifier. (It is very useful when only reserved words or some illegal identifiers are used as attribute names on that line)
The code copy is as follows:
var side = 1;
var square = {"left":{x:px,y:py},
'right':{x:p.x+side,y:p.y+side}}
Chapter 67 will also discuss the initialization expressions of objects and arrays again.
3. Function expressions
Function definition expression defines a javascript function. The value of the expression is this newly defined function. In a sense, function definition expressions can become direct function quantities, and function expressions can be called "direct function quantities", after all object initialization expressions are also called "direct object quantities". A typical function definition expression contains the keyword function, followed by a pair of parentheses, a comma-separated list, and the list contains 0 or more identifiers (parameter names). Then follow the javascript code segment (function body) wrapped in curly braces.
var square = function(x){ return x*x};
Function definition expressions can also contain the name of the function. Functions can also be defined by function statements, rather than function expressions. More content will be described in Chapter 8.
4. Attribute access expression
The attribute access expression operation obtains the value of an object or an array element. JavaScript defines two methods for property access.
The code copy is as follows:
expression . indentifier
expression [expression]
The first way is to write an expression followed by a period and an identifier. The expression specifies the object, and the identifier specifies the attribute Mingchuan to access.
Chapter 2 is written using square brackets, which is an expression (this method is suitable for objects and arrays). The second expression specifies the Mingchuan property to be accessed or the index representing the array element to be accessed. Here are some specific examples
The code copy is as follows:
ox //=>1x attribute of expression o
oyz //=>3 z attribute of expression oy
o.["x"] //=> 1 object o's x attribute
a[1] //=>4 Element with the index of expression a is 1
a[2]["1"]//=>6 Element with index 1 in expression a[2]
a[0].x //=>1: x attribute of expression a[0]
Regardless of the form of attribute access expressions used, the expressions before "." and "[" are always evaluated first. If the evaluation result is null or undefined, the expression will throw a type error exception because neither of these values can contain any attributes. If the operation result is not an object or an array, javascript will convert it into an object (Chapter 3, Section 6)
Although the .identifier is written more simply, it should be noted that this method only applies to the attribute name to be accessed and is a legal identifier. And you need to know the name of the attribute to access. If the property name is a reserved word or contains spaces and punctuation marks and is a number (for an array), square brackets must be written. When the attribute name is a value derived from an operator rather than a fixed value, square brackets must be written. (Chapter 6, 2, 1 bar)
5. Transport expression
An invocation expression in javascript is a syntax representation of calling (or executing) a function or method. It starts with a function expression that refers to the function to be called. The function expression is followed by a pair of parentheses, with a comma-separated parameter list. There can be 0 parameters or multiple parameters.
f(0) //f is a function expression: 0 is a parameter expression.
Math.max(x,y,z) //Math.max is a function; x, y and z are parameters
a.sort() //a.sort() is a function that has no parameters.
When an expression is called for evaluation, first calculate the function expression, then calculate the parameter expression to obtain a set of parameter values. If the value of the function expression is not a callable object, a type error exception is thrown. The values of the parameters are then assigned to the formal parameters, which are defined when defining the function. Next, execute the function body. If the function uses the return statement to give a return value, then this return value is the value of the entire calling expression. Otherwise, the value of the calling expression is undefined. The details of the function call - including the number of formal parameter expressions and the number of actual parameters in the function definition - will be explained in detail in Chapter 8.
Any calling expression contains a pair of parentheses and expressions before the left parentheses. If this expression is a property access expression, then this call is called "method invitation". When executing a function body in a method call, the object and array that are accessed as attributes are the pointer of this in the calling method. This feature makes it possible for functions (whose OO name is "method") to call their host object (more on Chapter 9).
6. Object creation expression
Object creation expression creates an object and calls a function (constructor) to initialize the object's properties. Object creation expressions are very similar to function calling expressions, except that there is an additional keyword new before object creation expressions:
new Object()
new Point(2,3)
If the object creation expression does not require any parameters to be passed to the constructor, then this pair of brackets can be omitted. More details of the constructor will be explained in Chapter 9
new Object
new Point
7. Overview of operators
Operators in javascript are used to calculate table expressions, comparison expressions, logical expressions, assignment expressions, etc.
It should be noted that most operators are represented by punctuation marks, such as delete and instanceof. Whether it is keyword operators or symbolic operators, the operators represented are regular operators, and their syntax is very concise.
The priority of the subscript operator is sorted, and the priority of the previous operator is higher than the priority of the subsequent operator. Operators separated by horizontal Huafeng have different priorities.
A represents the binding nature of the operator.
L from left to right or R (from right to left)
The list of title N represents the number of operands.
Type represents the type of the expected operand, and the result type of the operator (after the "→" symbol)
| Operators | operate | A | N | type |
| ++ | Front/after increment | R | 1 | lval→num |
| -- | Reduce before and after | R | 1 | lval→num |
| - | Seek inverse | R | 1 | num→num |
| + | Convert to numbers | R | 1 | num→num |
| ~ | Reverse bit by bit | R | 1 | int→int |
| ! | Logical non-logical | R | 1 | bool→bool |
| delete delete | Delete attributes | R | 1 | lval→bool |
| typeof | Detect operation type | R | 1 | any→Str |
| void | Return undefined value | R | 1 | any→undef |
| * , /, % | Multiplication and division to find the remainder | L | 2 | num, num→num |
| +,- | Add, subtract | L | 2 | num, num→num |
| + | String connection | L | 2 | str, str→str →str |
| << | Left shift | L | 2 | int, int→int |
| >> | Right shift | L | 2 | int, int→int |
| >>> | Unsigned right | L | 2 | int, int→int |
| <,<=,>,>= | Compare the order of numbers | L | 2 | num, num→bool |
| <,<=,>,>= | Compare the order in letters | L | 2 | str, str→bool |
| instanceof | Test object class | L | 2 | obj, func→bool |
| in | Test whether the attribute exists | L | 2 | str,obj→bool |
| == | Equal judgment | L | 2 | any, any→bool |
| ! = | Unsatisfied judgment | L | 2 | any, any→bool |
| === | Judge the qualities | L | 2 | any, any→bool |
| ! == | Judge non-constant | L | 2 | any, any→bool |
| & | bitwise and | L | 2 | int, int→int |
| ^ | bitwise xor | L | 2 | int, int→int |
| | | bitwise or | L | 2 | int, int→int |
| && | Logic and | L | 2 | any, any→any |
| || | Logical or | L | 2 | any, any→any |
| ?: | Conditional operator | R | 3 | bool, any, any→any |
| = | Variable assignment or object attribute assignment | R | 2 | lval, any→any |
*= /= %= += -= &= ^= |= <<= >>= >>>= | Compute and assign values | R | 2 | lval, any→any |
| , | Ignore the first operand, Returns the second operand. | L | 2 | any, any→any |
i. Number of operands
Operators can be classified by the number of operands.
Most operators in javascript are binary operators that combine two expressions into a slightly more complex expression.
JavaScript also supports some unary operators that convert one expression to another slightly more complex expression. The "-" operator in the expression -x is a unary operator. It is to find a negative value for x.
JavaScript supports a ternary operator: the conditional judgment operator "?:", which combines three expressions into one expression
ii. Operand type and result type
Some operators can be used for any data type, but they still want them to operate on data of the specified type.
iii.lvalue
Assignment operators and other few operators in the table expect their operand lval type, lvalue is an ancient term. It means that "expressions can only appear on the left side of the assignment operator". In JavaScript, variables, object properties, and array elements are all lvalues. The ECMAScript specification allows a range built-in function to return an lvalue, but defined functions cannot return an lvalue.
iiii. operator priority
In the table above, the operators shown are sorted from high to low by priority, with a set of operators within each horizontal separator having the same priority. Operator priority controls the order in which operators are executed. Operators with high (top of table) are always executed higher than operators with low priority (bottom of table).
See the following expression
w=x+y*z;
The multiplication operator "*" has a higher priority than the addition "+", so multiplication is executed first. Then, since the assignment operator "=" has the lowest priority. Therefore, the assignment operation is performed after the expression on the right calculates the result.
The priority of the operator can be written using garden brackets. The above expression can be written like this.
w = (x + y) * z;
It should be noted that the priority of property access expressions and calling expressions is higher than that of all operators in the table.
typeof my.Function[x](y)
Although typeof is one of the highest priority operators, typeof is also executed after two property accesses and function calls.
In fact, if you are really unsure of the priority of the operator you are using, the easiest way is to use garden brackets to force the order of operations. Some important rules should be memorized: multiplication and division are higher than addition and subtraction, and the priority of assignment operations is very low, and are usually executed last.
iiiiiii.Operationality
In this section, the column titled A illustrates the noduleness of the operator. L refers to the combination from left to right, and R refers to the combination from right to left. Tuberculosis specifies the order of operations in multiple operator expressions with the same priority.
For example, the subtraction operation is performed in a combination from left to right.
The code copy is as follows:
w = x - y - z
Like this code:
The code copy is as follows:
w = ((x - y) - z)
Conversely, the following expression:
The code copy is as follows:
x = ~-y;
w = x = y = z;
q=a?b:c?d:e?f:g;
Exactly the same as this code
The code copy is as follows:
x=~(-y);
w=(x=(y=z));
q=a?b:(c?d:(e?f:g))
Because unary operators, assignments and ternary condition operators all have a combination from right to left.
iiiiiiiii.Operation order
The priority and binding of operators define their order of operations in the assignment equation, but does not specify the order of operations in the calculation process of word expressions. JavaScript always computes expressions strictly in order from left to right, for example:
In the expression w=x+y*z, the expression w will be calculated first, then x, y and z will be calculated, and then the values of y will be multiplied by z, adding the value of x. Finally, the variable or attribute referred to by its expression w is referred to. Adding a circle bracket to an expression will change the relationship between multiplication, addition and assignment operations. But the order from left to right will not change.
8. Arithmetic expressions
This section covers those arithmetic calculation operators, as well as arithmetic operations on operands. Multiplication, division and subtraction operators are very simple. The addition operation is a separate section because the addition operator can operate string concatenation and its type conversion is somewhat special.
The basic arithmetic operators are *, /, %, +, -. In addition to +addition, other operators are particularly simple. They are just converted into numbers when necessary, and then they can find the product, quotient, residual (module) and difference. All those operations that cannot be converted to numbers will be converted to NaN values. If the operand (or conversion result) is a NaN value, the arithmetic operation result is also NaN
The operator "/" divides the second operand by the first operand, if you have used programming languages that distinguish integer and floating point. Then when you divide an integer by an integer, the desired result is also an integer. In JavaScript, all numbers are floating-point numbers, and the result of division operations is also floating-point types. For example, the result of 5/2 is 2.5, not 2. The result of the operation with the divisor 0 is positive infinity or negative infinity. And the result of 0/0 is NaN. All these operations will not report errors.
The operator "%" calculates the modulus of the first operand to the second operand, in other words, the first operand is divided by the remainder of the second operand. The result symbol is consistent with the first operating mouse (divided) symbol. For example, the result of 5%2 is 1, and -5%2 is -1.
The operands of the remnant operator are usually integers, but they are also suitable for floating-point numbers. 6.5%2.1 result is 0.2. (0.19999999999999999973)
i. "+" operator
The binary addition operator "+" can add two numbers or string concatenate operations:
The code copy is as follows:
1+2 //=> 3
"hello" + "" + "there" // =>"hello there"
"1"+"2" //=>"12"
When both operands are numbers or are strings, the calculation results are obvious. However, for other cases, some necessary type conversion is required. And the behavior of the operator depends on the result of the conversion of the type. Technically speaking, the behavior of the addition operator is:
If an operand is an object, the object will follow the conversion rule of the object to the original value to the original class value (see Chapter 3, Section 8, 3). Date performs conversion on the object toString() method, while other objects perform conversion via the valueOf() method (if the valueOf() method returns a primitive value). Since most objects do not have the available valueOf() method, they will use the toString() method to perform the crawling
After the object to the original value is converted, if one of the operations is a string, the other operand will also be converted to a string. Then do string concatenation.
Otherwise, both operands will be converted to numbers (or NaN) and then added.
Here are some examples
The code copy is as follows:
1 + 2 //=>3 Addition
"1" + "2" //=>"12" String connection
"1" + 2 //=> "12" numbers are converted to strings and concatenated
1 + {} //=>"1[object object]": The object is converted to a string and then string concatenation is performed.
true + true //=>2 Boolean value is converted to a number and added
2 + null //=>2 null converted to 0 and do addition
2 + undefined //=>NaN undefined converts to NaN for addition
Finally, it is important to note. When the plus sign operation is used in line with strings, the effect of addition on the order of operations should be considered. That is to say, the operation result depends on the operator's operation order, for example
The code copy is as follows:
1 + 2 + "bmice" //=> "3 bmice"
1 + (2 + "bmice") => "12bmice"
ii. unary operator
The unary operator acts on a separate operand. and generate a new value. In JavaScript, unary operators have high priority and are all right-combined. This section describes the unary operators (+,-,++ and --), and when necessary, they convert operations to numbers. It should be noted that + - is a unary operator, and is also a binary operator.
One-yuan addition+
The unary addition operator converts the operand number into a number (or NaN) and returns the converted number. If the operand itself is a number, then the number is returned directly.
One-yuan subtraction-
When the - sign is a unary operator, it will convert the operand into a number as needed, and then change the symbol of the operation result.
Increment ++
Increment the "++" operator to increment (+1) the operand, and the operand is an lvalue (variable, array element, or object attribute). The operator converts operands to numbers. Then add 1 to the number and reassign the value after adding 1 to the variable, array element or object attribute.
Increment ++ operation returns the value dependent on its position on the operand.
When the operator is before the operand number, it is called the "pre-increment" operator, which incrementally calculates the operand and returns the calculated value.
When the operator is after the operand, it is called the "post-increment" operator. It performs incremental calculations on the operand, but returns the unincremented value that is used for incremental calculations. like
var i = 1,j = ++i //The values of i and j are both 2
var i = 1,j = i++; //i is 2, j is 1
It should be noted that the sum of ++x=x+1 is exactly the same. The "++" operator never performs string concatenation operations. It will always convert the operand into a number and increase it by 1. If x is the string "1", the result of ++x is the number 2, and x+1 is the string "11"
The decreasing and incrementing operations are the same, which converts operands into an array and then subtracts by 1.
iii. bit operator
The bit operator can perform lower-level bitwise operations on binary data represented by numbers. Although they are not traditional pure mathematical operations, they are also classified here as arithmetic operators because they act on operations of numeric types and return numbers. These operators are not common in javascript. (Not described here, please use Baidu for details~-~)
9. Relational expressions
This section describes the relationship operators of javascript. Relational operators are used to test the relationship between two values (equality, less than or "attributes") and return true and false according to whether the relationship exists. Relational expressions always return a boolean value, and usually use relational expressions in if while or for statements (Chapter 5) to control the execution process of the program.
The next few sections will talk about equality and unequal operations, comparison operators and the other two relationship characters in javascript in and instanceof
i equality and unequal operators
The "==" and "===" operators are used to compare whether two values are equal, and the two operators allow operators of any type. Return true if equal, otherwise return false. "===" is also called the strict equality operator (sometimes called the identity operator), which is used to detect whether two operands are strictly equal. The "==" operator is called the equality operator. It is used to detect whether two operands are equal. The equality definition here is loose and allows type conversion.
JavaScript supports the "=", "==", "===" operators, you should understand the differences between (assignment, equality, identity) operators. And be careful when programming. In order to reduce confusion, "="" should be called "get or assign", "=="" should be called "equal", and "===" should be called "strictly equal".
The rules of the "!=" and "!==" operators are "==", the inverse of the "===" operator, and "!" is a Boolean non-operator. We call "!=", "!==" unequal and not strictly equal.
Comparison of javascript objects is a comparison of references, not a comparison of values. Objects and themselves are equal, but they are not equal to people and objects. If two objects have the same number of attributes, the same attribute names and values, they are still unequal. The array elements at the corresponding position are equal and two arrays are also unequal.
The strict equality operator "==="First calculate the value of the operand, and then compare these two values. There is no conversion in the comparison process.
If the two value types do not want to be the same, they are not equal
If both values are null or undefined, they are not equal
If both values are boolean true or false, they are equal
If one of the values is NaN, or both are NaN, they are not equal, and NaN and other values are not equal, including itself.
If two values are numbers and are equal, they are equal. If a value is 0 and a value is -0, they are also equal.
If the two values are strings and the 16-digit numbers (see Chapter 3, 2) contained in the corresponding bits are exactly equal, they are equal. If their length or content is different, they are not equal. The two strings may have exactly the same function and the characters displayed are the same, but have 16-bit values that are not encoded. JavaScript does not perform standard conversions on Unicode, so such strings are not equal in comparison with the "===" and "==" operators. String.localeCompare() in the third part provides another way to compare strings.
If two reference values point to the same object, array, or function, they are equal. If pointing to different objects, they are inequality, although the two objects have exactly the same properties.
The equality operator "==" is similar to the identity operator, but the equality operator is not strictly compared. If the two numbers are not of the same type, the equality operator tries to do some type conversion and then compares.
If the two operations are the same, the comparison rules for the equality operators above are the same. If strictly equal, then the comparison results are equal. If they are not strictly equal, the comparison results are not equal.
If the two operation types are different, the "==" equal operator will also consider them equal. Detection of equality will follow the following rules and type conversions:
If a type is null and let the other be undefined, they are equal
If one value is a number and the other is a string, convert the string to a number first, and then use the converted value for comparison.
If a value is true, it is converted to 1 and then compared. If a value is false, it is converted to 0 and compared.
If one value is an object and the other is a number or a string, use the conversion rules of the method in Chapter 3, Section 8, 3 to convert the object to the original value and then compare it. The object is converted to the original value through the toString() method or the valueOf() method. The built-in classes in the core of the javascript language first try to use valueOf() and then try to use toString(). In addition to the date class, the date class can only be converted through toString(). Objects that are not in the core of the javascript language are converted to original values through methods defined in the implementation.
The comparisons between other types are not equal
Here is a small example of equal judgment
"1" == true
The result of this expression is true, which indicates that the comparison results of completely different types of values are equal. The boolean value is true first converted to the number 1 and then the comparison is performed. Next the string "1" is also converted to the number 1, because the values of the two numbers are equal, so the result is true.
ii. Comparison operator
Less than (<)
If the first operand is smaller than the second operand, the "<" operation result is true, otherwise it is false
Less than or equal to (<=)
Greater than (>)
Greater than or equal to (>=)
.... (No detailed introduction to the meaning)
The operands of the comparison operator may be of any type. However, only numbers and strings can actually perform comparison operators, so those operands that are not numbers and strings will be type-converted. The type conversion rules are as follows:
If the operand is an object, it will be converted to the original value according to the conversion rules described in Section 3, Section 8, 3: If valueOf() returns a primitive value, then use this original value directly. Otherwise, use the conversion result of toString() for comparison.
After converting to the original value, if both operands are strings, the two strings will be compared in the order of the alphabet. The "alphabet order" mentioned here is the index order of the 16-bit Unicode characters that make up the two strings.
After the object is converted to the original value, if at least one operand is not a string, both operands will compare the values of the numbers. 0 and -0 are equal. Any other number in the Infinty wall is large (except infinty itself), -infinty is smaller than any number (except itself). If an operand (or converted) is NaN, the comparison character always returns false
For numeric and string operators, the plus sign operator behavior is different from the comparison operator. The former prefers strings and performs string concatenation operations if one of its operands is a string. Comparative operators prefer numbers only when both operands are string strings. Only then will the string comparison be performed.
The code copy is as follows:
1 + 2 //=>3 Addition, the result is 3
"1" + "2" //Connect string, result is "12"
"1" + 2 //Connect string, 2 is converted to "2", result is "12"
11 < 3 //The number comparison, the result is true
"11" < "3" //Standard comparison, the result is true
"11" < 3 // Comparison of numbers, "11" is converted to 11, and the result is true
"one" < 3 //Number comparison, "one" is converted to NaN, and the result is false
Finally, it should be noted that when judging equality, the "<=" and ">=" operators do not rely on the equality operator and the strict equality operation comparison rules. On the contrary, the operator Zhi who is less than or equal to is simply "not greater than", while the operation that is greater than or equal to is only "not less than". With only one exception, when the operand (after converted) is NaN, all 4 comparison operators will return fasle.
iii.in operator
The in operator wants its left operand to be a string or can be converted to a string, and hopes it is an object to the right. If the object on the right has an attribute name called the left operand value, the expression returns true. For example
The code copy is as follows:
var point = {
x: 1,
y: 1
} //Define an object
"x" in point //=>true The object has a property named x
"z" in point //=>false The object has no name z attribute
"toString" in point // =>true object inherits the toString method
var data = [7, 8, 8]
"0" in data //=>true The array contains 0
1 in data //=>true Convert number to string
3 in data //=>fase No element with index of 3
iiii.instanceof operator
The instanceof operator wants the left operator to be an object and the right operand indicates the object's class. If the object on the left is an instance of the class on the right, the expression returns true; it is responsible for returning false. Chapter 9 will talk about it. Classes of javascript objects are defined by initializing their constructors. In this way, the right operand of instanceof should be a function. for example:
The code copy is as follows:
var d = new Date(); //Construct a new object
d instanceof Date; //The result of the calculation is true, d is created by Date()
d instanceof Object //The result of the calculation is true, and all objects are instances of Object
d instanceof Number //The result of the calculation is false, d is not a Number object
var a = [1,2,3] //Array direct quantity to create an array
a instanceof Array //The result of calculation is true a is an array
a instanceof Object //true All arrays are objects
a instanceof RegExp //fasle array is not a regular expression
It should be noted that all objects are instances of Object. When the instanceof disk is an instance of a class, this judgment is also called the detection of "superclass". If the left operation object of instanceof is not an object, instanceof returns false. If the right-hand operation is not a function, an error-of-type exception is thrown.
In order to understand how the instanceof operator works, we must first understand the "prototype chain". The prototype chain, as the inheritance mechanism of JavaScript, will be described in detail in Chapter 6, Section 2, 2.
In order to calculate the expression o instanceof f , javascript first calculates f.prototyoe, and then query o in the prototype chain. If it is found, then o is an instance of f (or the parent class of f), then return true. Otherwise false
10. Logical expressions
Logical operators "&&", "||", "!" are Boolean arithmetic operations on operations, which are often used together with relational operators. Logical operators combine multiple relational expressions to form a more complex expression.
i. Logic and
The "&&" operator can be understood from three different levels. The simplest understanding is that when operands are booleans, "&&" performs a Boolean and (AND) operation on both boolean values. It returns true only when the first operand and the second operand are true. If one of the operands is false, it returns false.
"&&" is used to connect two relational expressions
x == 0 && y == 0; //Return true only when x and y are both 0
Relational expressions always return true or false, so when used like this, "&&" itself also returns true or false. Relational operators have higher priority than "&&" (and "||"), so expressions like this can be written with confidence without adding parentheses.
The "&&" operand is not necessarily a Boolean value. Recall that some values can be regarded as "true value" and "false value". (For example, in Chapter 3, the false value is: false null undefined 0 -0 NaN and "", all and other values including all objects are true values). The second level of understanding of "&&" is that "&&" can perform Boolean and (AND) operations on true and false values. If both operands are true, then a true value is returned; otherwise, at least one operand is false. In JavaScript, expression statements treat it as true or false when using boolean values, so in fact "&&" does not always return true and false. But it is not a big deal.
It should be noted that the above mentioned operators return "true value" and "false value", but did not explain what the "true value" or "false value" is. For this reason, we will discuss our understanding of the third level of "&&". The operator first calculates the value of the left operand, that is, first calculates the expression on the left side of "&&". If the calculation result is a false value, the result of the entire expression must be a false value. Therefore, "&&" simply returns the value of the left operation, and does not calculate the operand on the right.
The code copy is as follows:
var o = {
x: 1
};
var p = null;
o && ox; //=>1 : 1:0 is the true value, so the return value is ox
p && px //= null :p is a false value, so it is returned without calculating px
This is crucial for understanding that "&&" may not calculate the right operand. In the above code, the value of the variable P is null, and an exception error will be thrown if px is calculated. Therefore, px is calculated only if p is the true value (can't be null or undefined).
The behavior of "&&" is sometimes called "short circuit". We often see that a lot of code uses this to execute code conditionally. For example, the following two codes are equivalent
The code copy is as follows:
if (a == b) stop(); //Only when a==b can stop() be transferred
(a == b) && stop(); //Same as above
Generally speaking, be extra careful when the expression on the right side of "&&" has side effects (assignment, increment, decrement, and function call expressions). Because when these expressions with side effects are executed, they depend on the calculation results of the left-handed mouse.
Although "&&" can perform some complex expression operations according to the understanding of the second and third layers, in most cases, "&&" is only used to do boolean calculations for true and false values.
ii. Logical or (||)
The "||" operator performs a Boolean or (OR) operation on two operands. If one of them is a true value, it returns the true value, and both operands are false values, returning the false value.
尽管“||”运算符大多情况下只是做简单的布尔或(OR)运算,和“&&”一样,也具备一些更复杂的行为,它首先计算第一个操作数的值,也就是说回首先计算左侧的表达式,如果计算结果为真,则返回真值,否则,再计算第二个值。
和“&&”一样,用于应该避免右操作数包含一些具有副作用的表达式,除非你目地明确在右侧使用带副作用的表达式,而有可能不会计算右侧的表达式。
这个运算符最常用的方式是用来从一组备选的表达中选取第一个真值的表达式。
The code copy is as follows:
//如果max_width已经定义了,则直接使用它。赋值在preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量。
var max =max_width || preferences.max_windth || 500;
这种贯用法通常在函数体内,用来给参数提供默认值。
The code copy is as follows:
//将o成功的属性复制到p中,并返回p
function copy(o, p) {
p = p || {}; //如果向参数p没有传入任何对象,则使用一个新创建对象。
//函数体内的主逻辑
iii.逻辑非(!)
"!"运算符是一元运算符,它放置在一个单独操作数之前。它的目的是将操作数的布尔值求反。
和"&&"、"||"运算符不同,“!”运算符首先将其操作数转换为布尔值(参考第三章的讲诉规则),然后再对布尔值求反。也就是"!"总是返回true和false。并且,可以通过使用两次逻辑非运算来得到一个值的布尔值:(!!x,参照第三章第八节第2小节)
“!”具有很高的优先级,并且和操作数紧密的绑在一起,如果希望对p && q,则需要园括号!(p && q)。如下代码:
The code copy is as follows:
!(p && q) === !p || !q
!(p || q) === !p && !q
对于p和q取任何值,这两个表达式永远成立。
11.赋值表达式
javascript使用"="运算符给变量或者属性来赋值,例如:
The code copy is as follows:
i = 0 //将变量i设置为0
ox = 1 //将对象o的属性x 设置为1
“=”运算符希望它的左操作数为一个左值:一个变量或者对象属性(或数组元素),它的右操作鼠可以是任意的类型的任意值。赋值表达式的值就是右操作数的值。赋值表达式的副作用是,右操作数的值赋值给左侧的变量或对象属性。这样的话,后续对这个变量和对象的属性的引用都将得到这个值。
尽管赋值表达式的值非常简单,但有时候会看到一些复杂表达式包含赋值表达式的情况。例如:将赋值和检测操作放在一个表达式中:
The code copy is as follows:
(a = b) == 0
如果这样的话,应该清楚地知道"="和"=="区别!,需要注意的是,“=”有非常低的优先级,通常在一个较长的表达式中用到一条赋值语句时,需要补充园括号以保障正确的运算顺序。
赋值操作符的结合性是从右至左,也就是说,一个表达式中出现了多个赋值运算符,运算顺序也从右至左,因此,可以通过以下方式对多个变量赋值。
The code copy is as follows:
i=j=k=0; //把三个变量初始化为0
带操作的赋值运算:
除了常规的赋值运算外,javascript还支持需要其他的赋值运算符,这些运算符将赋值运算符合其他的运算符连接起来。提供一种更为快捷的运算方式。例如+=运算符执行的是加法运算符和赋值操作,下面的表达式:
total += salaes_tax;
和下面的表达式等价的
total = total + salaes_tax
运算符“+=”可以作用于数字或字符串,如果其操作是数字,它将执行加法运算和赋值操作;如果是字符串,他就执行字符串的连接和赋值操作。
此类型的运算符还包括,"-=","*=","&="等,如下表赋值运算符
运算符示例等价于
+=a+=ba=a+b
-=a-=ba=ab
*=a*=ba=a*b
/=a/=ba=a/b
%=a%=ba=a%b
<<=a<<=ba=a<<b
>>=a>>=ba=a>>b
>>>=a>>>=ba=a>>>b
&=a&=ba=a&b
|=a|=ba=a|b
^=a^=ba=a^b
大多数情况下,表达式为
a op =b
这里的op代表一个运算符,这个表达式等价于
a =a op b
在第一行中,表达式a计算了一次,在第二行中,表达式a计算了两次。
只有a包含具有副作用的表达式(比如函数调用和赋值操作)的时候,两者才不等价。如下两个表达式不等价
The code copy is as follows:
data[i++] *= 2;
data[i++] = data[i++] * 2
12.表达式计算
和很多解释性语言一样,javascript同样可以解释运行由javascript源代码组成的字符串,并产生一个值。javascript通过全局函数eval()来完成这个工作。
eval("3+2") //=>5
动态判断源代码中的字符串是一种强大语言的特性,几乎没有必要在实际中应用。如果你使用了eval(),你应该仔细考虑真的需要它。
下面降价eval()基础用法,并介绍两种严格使用它的方法,从代码优化的角度来讲,这两种方法对原有的代码影响是最小的。
i.eval (eval()是一个函数,但由于它已经被当做运算符来对待了。)
eval()只有一个参数,如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成javascript进行编译(parse),如果编译失败则抛出一个语法错误(SyntaxError)。如果编译成功,则开始执行这段代码,并返回字符串中最后一个表达式或语句的值,如果最后一个表达式没有语句或者值,则最终返回undefined。如果字符串抛出一个异常,这个异常把该调用的传给eval()
关于eveal()最重要的是,它使用了调用它的变量作用域环境,也就是说,它查找变量的值和定义新变量和函数的操作和局部的代码作用域中的代码一样。如果一个函数定义了一个局部变量x,然后调用了eval("x"),它会返回局部变量的值。如果它调用eval("x=1"),它会改变局部变量的值。如果函数调用了eval("var y=3;")它声明一个新的局部变量y。同样的,一个函数可以通过如下代码声明一个局部函数:
eval("function f(){return x+1;}");
如果最顶层的代码中调用了eval()。当然它会作用于全局变量和全局函数。
ii.全局eval()
eval()具有改变局部变量的能力,这对javascript优化器来说,是一个很大的问题,然而作为一种权宜之计,javascript征对那行调用了eval()函数所做的优化并不多。但当脚本定义了一个别名,并且用令一个名称来调用它,javascript解释器又如何工作呢,为了javascript解释器更加简化。ECMAScipt3标准规定了任何解释器都不允许对eval()赋予别名。如果eval()使用别的别名来调用的话,则会抛出EvalError异常。
实际上,大多数的实现并不是这样做的。当通过别名调用时,eval()会将其字符串当成顶层的全局代码来执行。执行代码可能会定义新的全局变量和全局函数。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值。但却不能修改或修改主调函数中的局部变量,因此这不会影响到函数内的代码优化。
ECMAScript5是反对使用EvalError的,并且规范了eval()的行为。“直接的eval”,当直接使用非限定的“eval”名称,来调用eval()函数时,它总共是在它的上下文作用域内支线。其它间接调用则使用全局函数为其上下文作用域。并且无法读、写、定义局部变量和函数。下面有一段代码实例:
The code copy is as follows:
var geval = eval; //使用别名调用eval将是全局eval
var x = "global",
y = "global"; //两个全局变量
function f() { //函数内执行的局部eval
var x = "local" //定于局部变量
eval("x += 'changed';"); //直接eval更改了局部变量的
return x; //返回更改后的局部变量
}
function g() { //这个函数执行了全局eval
var y = "local" //定义了局部变量
geval("y += 'changed';"); //间接改变了局部变量的值
return y; //返回未更改的局部变量
}
console.log(f(), x); //更改了局部变量,输出local changed global
console.log(g(), y); //更改了全局变量,输出local globalchanged
13.其它运算符。
javascript支持很多其它各种各样的运算符。
i.条件运算符(?:)
条件运算符是javascript中的唯一一个三元运算符。通常这个运算符写成"?:",这个运算符拥有三哥操作数,第一个操作数在"?"之前,第二个操作数在“?”和":"之间。第三个操作数早在":"之后,例如
x > 0 ? x : -x; //求x的绝对值
条件运算符的操作数可以是任意类型。第一个操作数当成布尔值,如果它是真值,那么将计算第二个操作数,并返回计算结果。赋值如果第一个值操作数是假值,那么将计算第三个操作数。并返回计算结果。第二个和第三个操作数总会计算其中之一。不可能两者同时进行。其实使用if语句也达到同样的效果(5.4.1),“?:”运算符只是提供了一种简写形式。这里是一个"?:"的典型使用场景,判断一个变量是否有定义,如果有定义则使用它,如果无定义,则使用一个默认值。
The code copy is as follows:
grett = "hello" + (username ? username : "three");
和以下的代码是等价的,但上面的更加简洁
The code copy is as follows:
grett = "hello";
if (username)
grett += username;
else
grett + "three"
ii.typeof()运算符
typeof是一元运算符,放在单个操作数前面,操作数可以是任何类型,返回值表示操作类型的一个字符串。
The code copy is as follows:
x __ typeof x
undefined __ "undefined"
null __ "object"
ture或false __"boolean"
任意数字或NaN __ "Number"
任意字符串__ "String"
任意函数__ "function"
任意内容对象(非函数)__ "object"
任意宿主对象__ 由编译器各自实现的字符串,但不是"undefined" "boolean" "number" "string"
typeof最常用的用法写在表达式中们就像这样
(typeof value == "string") ? "" + value + "":value;
typeof运算符同样在swith语句中(5.4.3)非常有用,需要注意的是,typeof运算可以带上园括号。这样让typeof看起来像一个函数名,而非关键字
typeof(i)
iii.delete运算符
delete是一元操作符,它用来删除对象的属性或者数组的元素。就像赋值、递增、递减运算符一样。delete也是具有副作用的。它是用来做删除操作的。不是用来返回一个值的。
The code copy is as follows:
var o = {
x: 1,
y: 2
}
delete ox;
"x" in o; //=>false
var a = [1, 2, 3];
delete a[2]; // 删除数组中最后一个元素
2 in a; //=> false 元素2已经在数组中不存在了
a.length; //=>3,注意,数组长度并没有改变,尽管上一行删除了这个元素,但删除操作留下了一个洞。实际上并没有修改数组的长度,因此a的长度仍然为3
需要注意的是,删除属性或删除数组元素不仅仅设置了一个undefined值,当删除一个属性时,这个属性不复存在。读取一个不存在的值将会返回undefined.关于delete删除还有严格模式下的一些情况,需要学习的人自己试验,这里给一些例子。
The code copy is as follows:
var o = {x: 1,y: 2};
delete ox; //删除一个对象属性,返回true
typeof ox; //属性不存在,返回"undefined"
delete ox; //删除不存在的属性,返回true;
delete o; //不能删除通过var关键字声明的变量,返回false
delete 1; //参数不是一个左值。
this.x = 1;// 给全局定义一个属性,这里没有使用var
delete x ; //试图删除它,在非严格模式下返回true
//在严格模式下回抛出异常,这时使用"delete this.x"来代替
x; //运行时出错,没有定义x
6章第三节还有关于delete的讨论。
iii.void运算符。
void是一元运算符,在出现操作数之前,操作数可以是任何类型。这个运算符并不是经常使用:操作数会照常计算,但会忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用时使用void来程序更有意义。
这个最常用的带客户端url.在url写带有副作用的表达式,而void则让浏览器不显示在这个表达式的运算结果。
The code copy is as follows:
<a href="javascript:void window.open();">new</a>
iiii.逗号运算符。(,)
逗号运算符是二元运算符,它的操作数可以是任意类型。它首先计算左操作数,然后计算右操作数。
The code copy is as follows:
i = 0, j = 1, k = 2;
它和下面的代码基本上等价的
i = 0; j = 1; k = 2;
总是会计算左侧的表达式,但计算结果忽略掉,也就是说,只有左侧表达式具有副作用,才会使用逗号运算让代码变得更通畅。逗号运算符最常用的场景是for循环中,这个for循环通常有多个循环变量。
The code copy is as follows:
//for循环中的第一个逗号是var语句的一部分
//第二个逗号是逗号运算符
//它将两个表达式(i++和j++)放在一条(for循环中)语句中
for (var i = 0, j = 10; i < j; i++, j--);
console.log(i + j);