Una expresión es una frase en JavaScript, y el intérprete JavaScript calculará un resultado. Las cantidades de uso común en los programas son el tipo de expresiones más simple que son variables. Los nombres de variables también son una expresión simple, y su valor es el valor asignado a la variable.
Las expresiones complejas están compuestas de expresiones simples. Por ejemplo, una expresión de acceso a la matriz está compuesta de una expresión que representa una matriz, soportes cuadrados y una expresión entera. La nueva operación de expresión que forman es el valor del elemento en una posición específica en la matriz. La misma carta
Una expresión de llamadas numéricas consiste en una expresión que representa un objeto de función y 0 más de 0 expresiones de parámetros. El método más común para combinar expresiones simples en expresiones complejas son los operadores.
Este capítulo (este artículo) explicará todos los operadores de JavaScript. También explica las expresiones que no involucran operadores (como acceder a elementos de matriz y llamadas de funciones), y su sintaxis y estilo de programación son muy similares a los del lenguaje C.
1. Expresión de elementos
La expresión más simple es la "expresión original", que es la unidad más pequeña de una expresión: no contienen otras expresiones. Las expresiones originales en JavaScript contienen constantes o cantidades directas. Palabras clave y variables.
Una cantidad directa es un valor constante que aparece directamente en el programa. Parecen:
La copia del código es la siguiente:
1.23 // Cantidad directa
"Hola" // Stand Direct Cantidad
/ Pattern/ // Cantidad directa de expresión regular
Algunas palabras reservadas en JavaScript forman la expresión original
La copia del código es la siguiente:
verdadero // valor booleano: verdadero
falso // falso
nulo // devolver un valor: vacío
this // devuelve el objeto "actual"
A través del aprendizaje del Capítulo 3, a diferencia de otras palabras clave, esto no es una constante, y los valores que devuelve en diferentes partes del programa también son diferentes. Esta palabra clave a menudo aparece en la programación orientada a objetos. Esto devuelve el objeto del método cuadrado.
Finalmente, la tercera expresión original es una variable
La copia del código es la siguiente:
i // devuelve el valor de la variable i
suma // devuelve el valor de suma
Undefined // es una variable global, a diferencia de NULL, no es una palabra clave
2. Expresiones de inicialización de objetos y matrices.
La inicialización de objetos y matrices es en realidad objetos y matrices recientemente creados. Estas expresiones inicializadas a veces se denominan "Cantidad directa de objeto" y "Cantidad directa de matriz". Sin embargo, a diferencia de las cantidades directas booleanas, no son expresiones originales porque los miembros o elementos que contienen son subexpresiones.
La sintaxis de la expresión de inicialización de una matriz es muy simple, comencemos a continuación
La expresión de inicialización de una matriz está compuesta por un par de soportes cuadrados y una lista separada por comas. El resultado de inicialización es una matriz recién creada. Los elementos de una matriz son valores de expresiones separados por comas.
[] // una matriz vacía; [] Deja vacío en Its significa que la matriz no tiene elementos
[1+2,3+4] // matriz con dos elementos, el primero es 3, el segundo es 7
La expresión de inicialización del elemento en una expresión de inicialización de matriz puede ser una expresión de inicialización de la matriz. Es decir, las expresiones pueden ser anidadas
La copia del código es la siguiente:
var mat = [[1,2,3], [4,5,6], [7,8,9]];
Se pueden omitir elementos entre listas en la matriz, y el espacio estará lleno de indefinidos. Por ejemplo:
La copia del código es la siguiente:
var a = [1 ,,,, 5]
Cuatro de los elementos están indefinidos. Se deja una coma al final de la cantidad directa de la matriz, y no se creará un nuevo elemento con un valor indefinido.
Las expresiones de inicialización de objetos son muy similares a las expresiones de inicialización de matriz, excepto que los soportes cuadrados se reemplazan por soportes rizados. Y cada expresión de palabras contiene un nombre de atributo y un no cano como prefijo.
La copia del código es la siguiente:
var p = {x: 2.1, y: -3} // Un objeto con dos miembros de atributo
var q = {}; // Objeto vacío
qx = 2.1; qy = -3; // Los miembros del atributo de Q son los mismos que los de P
El objeto también se puede anidar directamente, por ejemplo
La copia del código es la siguiente:
var anh = {izquierda: {x: 2, y: 3},
Derecha: {x: 4, y: 5}}
Cuando JavaScript calcula el valor de una expresión de inicialización de objeto, las expresiones de objeto se calculan cada vez, y no tienen que incluir valores constantes: pueden ser cualquier expresión de JavaScript. Del mismo modo, el nombre de la propiedad en la cantidad directa del objeto puede ser una cadena en lugar de un identificador. (Es muy útil cuando solo se usan palabras reservadas o algunos identificadores ilegales como nombres de atributos en esa línea)
La copia del código es la siguiente:
lado var = 1;
var cuadrado = {"izquierda": {x: px, y: py},
'Right': {x: p.x+lado, y: p.y+lado}}
El Capítulo 67 también discutirá las expresiones de inicialización de objetos y matrices nuevamente.
3. Expresiones de funciones
La expresión de la definición de función define una función JavaScript. El valor de la expresión es esta función recientemente definida. En cierto sentido, las expresiones de definición de función pueden convertirse en cantidades de función directa, y las expresiones de función pueden llamarse "cantidades de función directa", después de todas las expresiones de inicialización de objetos también se denominan "cantidades de objeto directo". Una expresión de definición de función típica contiene la función de palabras clave, seguida de un par de paréntesis, una lista separada por comas, y la lista contiene 0 o más identificadores (nombres de parámetros). Luego siga el segmento de código JavaScript (cuerpo de funciones) envuelto en aparatos ortopédicos.
var cuadro = function (x) {return x*x};
Las expresiones de definición de función también pueden contener el nombre de la función. Las funciones también se pueden definir mediante declaraciones de funciones, en lugar de expresiones de funciones. Se describirá más contenido en el Capítulo 8.
4. Expresión de acceso a atributos
La operación de expresión de acceso de atributo obtiene el valor de un objeto o un elemento de matriz. JavaScript define dos métodos para el acceso a la propiedad.
La copia del código es la siguiente:
expresión . holgazanería
expresión [expresión]
La primera forma es escribir una expresión seguida de un período y un identificador. La expresión especifica el objeto, y el identificador especifica el atributo mingchuan para acceder.
El Capítulo 2 se escribe usando soportes cuadrados, que es una expresión (este método es adecuado para objetos y matrices). La segunda expresión especifica la propiedad Mingchuan a acceder o el índice que representa el elemento de matriz a acceder. Aquí hay algunos ejemplos específicos
La copia del código es la siguiente:
ox // => 1x atributo de expresión o
OYZ // => 3 Atributo Z de la expresión OY
o. ["x"] // => 1 objeto atributo x
a [1] // => 4 elemento con el índice de expresión a es 1
a [2] ["1"] // => 6 elemento con índice 1 en la expresión a [2]
a [0] .x // => 1: x atributo de expresión a [0]
Independientemente de la forma de expresiones de acceso a atributos utilizadas, las expresiones antes "." y "[" siempre se evalúan primero. Si el resultado de la evaluación es nulo o indefinido, la expresión lanzará una excepción de error de tipo porque ninguno de estos valores puede contener ningún atributo. Si el resultado de la operación no es un objeto o una matriz, JavaScript lo convertirá en un objeto (Capítulo 3, Sección 6)
Aunque el identificador. Se escribe de manera más simple, debe tenerse en cuenta que este método solo se aplica al nombre del atributo a acceder y es un identificador legal. Y necesita saber el nombre del atributo para acceder. Si el nombre de la propiedad es una palabra reservada o contiene espacios y signos de puntuación y es un número (para una matriz), se deben escribir soportes cuadrados. Cuando el nombre del atributo es un valor derivado de un operador en lugar de un valor fijo, se deben escribir soportes cuadrados. (Capítulo 6, 2, 1 bar)
5. Expresión de transporte
Una expresión de invocación en JavaScript es una representación de sintaxis de llamar (o ejecutar) una función o método. Comienza con una expresión de función que se refiere a la función a llamar. La expresión de la función es seguida por un par de paréntesis, con una lista de parámetros separados por comas. Puede haber 0 parámetros o múltiples parámetros.
F (0) // F es una expresión de función: 0 es una expresión de parámetros.
Math.max (x, y, z) //math.max es una función; x, y y z son parámetros
A.sort () //a.sort () es una función que no tiene parámetros.
Cuando se requiere una expresión para la evaluación, primero calcule la expresión de la función, luego calcule la expresión del parámetro para obtener un conjunto de valores de parámetros. Si el valor de la expresión de la función no es un objeto llamable, se lanza una excepción de error de tipo. Los valores de los parámetros se asignan a los parámetros formales, que se definen al definir la función. A continuación, ejecute el cuerpo de funciones. Si la función usa la declaración de retorno para dar un valor de retorno, entonces este valor de retorno es el valor de toda la expresión de llamadas. De lo contrario, el valor de la expresión de llamadas no está definido. Los detalles de la llamada de función, incluido el número de expresiones de parámetros formales y el número de parámetros reales en la definición de función, se explicarán en detalle en el Capítulo 8.
Cualquier expresión de llamadas contiene un par de paréntesis y expresiones antes de los paréntesis de la izquierda. Si esta expresión es una expresión de acceso a la propiedad, entonces esta llamada se llama "Invitación de método". Al ejecutar un cuerpo de funciones en una llamada de método, el objeto y la matriz a los que se accede como atributos son el puntero de esto en el método de llamadas. Esta característica hace posible que las funciones (cuyo nombre OO sea "método") llame a su objeto host (más en el Capítulo 9).
6. Expresión de creación de objetos
La expresión de creación de objetos crea un objeto y llama a una función (constructor) para inicializar las propiedades del objeto. Las expresiones de creación de objetos son muy similares a las expresiones de llamadas de funciones, excepto que hay una palabra clave adicional nueva antes de las expresiones de creación de objetos:
nuevo objeto ()
Nuevo punto (2,3)
Si la expresión de creación de objetos no requiere que se pasen ningún parámetros al constructor, entonces se puede omitir este par de soportes. Más detalles del constructor se explicarán en el Capítulo 9
nuevo objeto
nuevo punto
7. Descripción general de los operadores
Los operadores en JavaScript se utilizan para calcular expresiones de tabla, expresiones de comparación, expresiones lógicas, expresiones de asignación, etc.
Cabe señalar que la mayoría de los operadores están representados por signos de puntuación, como Delete e InstanceOf. Ya sea que se trate de operadores de palabras clave o operadores simbólicos, los operadores representados son operadores regulares, y su sintaxis es muy concisa.
La prioridad del operador de subíndice está ordenada, y la prioridad del operador anterior es mayor que la prioridad del operador posterior. Los operadores separados por Huafeng horizontal tienen diferentes prioridades.
A representa la naturaleza vinculante del operador.
L de izquierda a derecha o R (de derecha a izquierda)
La lista de Título N representa el número de operandos.
El tipo representa el tipo de operando esperado y el tipo de resultado del operador (después del símbolo "→")
| Operadores | funcionar | A | norte | tipo |
| ++ | Frente/después de incremento | Riñonal | 1 | lval → num |
| - | Reducir antes y después | Riñonal | 1 | lval → num |
| - | Buscar inverso | Riñonal | 1 | Num → Num |
| + + | Convertir a números | Riñonal | 1 | Num → Num |
| ~ | Bit inverso por bit | Riñonal | 1 | int → int |
| ! | Lógico no lógico | Riñonal | 1 | bool → bool |
| eliminar eliminar | Eliminar atributos | Riñonal | 1 | lval → bool |
| tipo de tono | Detectar el tipo de operación | Riñonal | 1 | cualquiera → str |
| vacío | Devolver valor indefinido | Riñonal | 1 | Cualquiera → Underef |
| *, /, % | Multiplicar y dividir para encontrar el resto | L | 2 | NUM, NUM → NUM |
| +,- | Agregar, restar | L | 2 | NUM, NUM → NUM |
| + + | Conexión de cadena | L | 2 | str, str → str → str |
| << | Desplazamiento izquierdo | L | 2 | int, int → int |
| >> | Cambio correcto | L | 2 | int, int → int |
| >>> | Derecho sin firmar | L | 2 | int, int → int |
| <, <=,>,> = | Compare el orden de los números | L | 2 | NUM, NUM → BOOL |
| <, <=,>,> = | Compare el pedido en letras | L | 2 | str, str → bool |
| instancia de | Clase de objeto de prueba | L | 2 | obj, func → bool |
| en | Prueba si el atributo existe | L | 2 | str, obj → bool |
| == | Juicio igual | L | 2 | cualquiera, cualquiera → bool |
| ! = | Juicio insatisfecho | L | 2 | cualquiera, cualquiera → bool |
| === | Juzgar las cualidades | L | 2 | cualquiera, cualquiera → bool |
| ! == | Juez no constante | L | 2 | cualquiera, cualquiera → bool |
| Y | bit a bit y | L | 2 | int, int → int |
| ^ | xor bit a bit | L | 2 | int, int → int |
| | | bit a bit o | L | 2 | int, int → int |
| && | Lógica y | L | 2 | cualquiera, cualquiera → cualquiera |
| || | Lógico o | L | 2 | cualquiera, cualquiera → cualquiera |
| ?: | Operador condicional | Riñonal | 3 | bool, cualquiera, cualquiera → cualquiera |
| = | Asignación de variable o asignación de atributos de objeto | Riñonal | 2 | lval, cualquier → cualquiera |
*= /= = %= += -= & = = ^= | = << = >> = >>> = | Calcular y asignar valores | Riñonal | 2 | lval, cualquier → cualquiera |
| , | Ignora el primer operando, Devuelve el segundo operando. | L | 2 | cualquiera, cualquiera → cualquiera |
i. Número de operandos
Los operadores pueden clasificarse por el número de operandos.
La mayoría de los operadores en JavaScript son operadores binarios que combinan dos expresiones en una expresión ligeramente más compleja.
JavaScript también admite algunos operadores unarios que convierten una expresión en otra expresión ligeramente más compleja. El operador " -" en la expresión -x es un operador unario. Es encontrar un valor negativo para x.
JavaScript apoya a un operador ternario: el operador de juicio condicional "?:", Que combina tres expresiones en una sola expresión
II. Tipo de operando y tipo de resultado
Algunos operadores pueden usarse para cualquier tipo de datos, pero aún desean que funcionen con datos del tipo especificado.
iii.lvalue
Los operadores de asignación y otros pocos operadores en la tabla esperan su tipo de operando Lval, Lvalue es un término antiguo. Significa que "las expresiones solo pueden aparecer en el lado izquierdo del operador de asignación". En JavaScript, las variables, las propiedades de los objetos y los elementos de matriz son todos los lvalues. La especificación de ECMAScript permite que una función incorporada de rango devuelva un LValue, pero las funciones definidas no pueden devolver un LValue.
IIII. prioridad del operador
En la tabla anterior, los operadores que se muestran se clasifican de alta a baja por prioridad, con un conjunto de operadores dentro de cada separador horizontal que tiene la misma prioridad. La prioridad del operador controla el orden en que se ejecutan los operadores. Los operadores con alto (parte superior de la tabla) siempre se ejecutan más altos que los operadores con baja prioridad (parte inferior de la tabla).
Ver la siguiente expresión
w = x+y*z;
El operador de multiplicación "*" tiene una prioridad más alta que la adición "+", por lo que se ejecuta primero la multiplicación. Luego, dado que el operador de asignación "=" tiene la prioridad más baja. Por lo tanto, la operación de asignación se realiza después de que la expresión a la derecha calcula el resultado.
La prioridad del operador se puede escribir con soportes de jardín. La expresión anterior se puede escribir así.
w = (x + y) * z;
Cabe señalar que la prioridad de las expresiones de acceso a la propiedad y las expresiones llamadas es más alta que la de todos los operadores en la tabla.
typeOf my.function [x] (y)
Aunque TypeOF es uno de los operadores de más alta prioridad, TypeOF también se ejecuta después de dos accesos de propiedad y llamadas a funciones.
De hecho, si realmente no está seguro de la prioridad del operador que está utilizando, la forma más fácil es usar soportes de jardín para forzar el orden de las operaciones. Se deben memorizar algunas reglas importantes: la multiplicación y la división son más altas que la adición y la resta, y la prioridad de las operaciones de asignación es muy baja, y generalmente se ejecutan al final.
iiiiiii.operacionalidad
En esta sección, la columna titulada A ilustra la nodulidad del operador. L se refiere a la combinación de izquierda a derecha, y R se refiere a la combinación de derecha a izquierda. La tuberculosis especifica el orden de operaciones en múltiples expresiones de operadores con la misma prioridad.
Por ejemplo, la operación de sustracción se realiza en una combinación de izquierda a derecha.
La copia del código es la siguiente:
w = x - y - z
Me gusta este código:
La copia del código es la siguiente:
w = ((x - y) - z)
Por el contrario, la siguiente expresión:
La copia del código es la siguiente:
x = ~ -y;
w = x = y = z;
P = A? B: C? D: E? F: G;
Exactamente lo mismo que este código
La copia del código es la siguiente:
x = ~ (-y);
w = (x = (y = z));
P = A? B: (C? D: (E? F: G))
Porque los operadores unarios, las tareas y los operadores de condición ternaria tienen una combinación de derecha a izquierda.
IIIIIIIII. Orden de operación
La prioridad y la unión de los operadores definen su orden de operaciones en la ecuación de asignación, pero no especifica el orden de operaciones en el proceso de cálculo de expresiones de palabras. JavaScript siempre calcula las expresiones estrictamente en orden de izquierda a derecha, por ejemplo:
En la expresión w = x+y*z, la expresión W se calculará primero, luego se calculará x, y y z, y luego los valores de y se multiplicarán por z, agregando el valor de x. Finalmente, se hace referencia a la variable o atributo mencionado por su expresión W. Agregar un soporte círculo a una expresión cambiará la relación entre las operaciones de multiplicación, adición y asignación. Pero el orden de izquierda a derecha no cambiará.
8. Expresiones aritméticas
Esta sección cubre esos operadores de cálculo aritmético, así como operaciones aritméticas en operandos. Los operadores de multiplicación, división y sustracción son muy simples. La operación de adición es una sección separada porque el operador de adición puede operar la concatenación de cadenas y su conversión de tipo es algo especial.
Los operadores aritméticos básicos son *, /, %, +, -. Además de +adición, otros operadores son particularmente simples. Simplemente se convierten en números cuando es necesario, y luego pueden encontrar el producto, el cociente, el residuo (módulo) y la diferencia. Todas esas operaciones que no se pueden convertir en números se convertirán en valores NAN. Si el operando (o resultado de conversión) es un valor nan, el resultado de la operación aritmética también es NAN
El operador "/" divide el segundo operando por el primer operando, si ha utilizado lenguajes de programación que distinguen el entero y el punto flotante. Luego, cuando divide un entero por un entero, el resultado deseado también es un entero. En JavaScript, todos los números son números de punto flotante, y el resultado de las operaciones de división también son tipos de puntos flotantes. Por ejemplo, el resultado de 5/2 es 2.5, no 2. El resultado de la operación con el divisor 0 es infinito o infinito negativo positivo. Y el resultado de 0/0 es nan. Todas estas operaciones no informarán errores.
El operador "%" calcula el módulo del primer operando al segundo operando, en otras palabras, el primer operando se divide por el resto del segundo operando. El símbolo de resultado es consistente con el primer símbolo de operación del mouse (dividido). Por ejemplo, el resultado del 5%2 es 1 y -5%2 es -1.
Los operandos del operador remanente suelen ser enteros, pero también son adecuados para números de punto flotante. 6.5%2.1 El resultado es 0.2. (0.19999999999999999973)
i. "+" operador
El operador de adición binaria "+" puede agregar dos números o operaciones de concatenato de cadena:
La copia del código es la siguiente:
1+2 // => 3
"Hola" + "" + "ahí" // => "Hola"
"1"+"2" // => "12"
Cuando ambos operandos son números o son cadenas, los resultados del cálculo son obvios. Sin embargo, para otros casos, se requiere alguna conversión de tipo necesaria. Y el comportamiento del operador depende del resultado de la conversión del tipo. Técnicamente hablando, el comportamiento del operador de adición es:
Si un operando es un objeto, el objeto seguirá la regla de conversión del objeto al valor original al valor de clase original (ver Capítulo 3, Sección 8, 3). La fecha realiza la conversión en el método objeto toString (), mientras que otros objetos realizan conversión a través del método valueOf () (si el método valueOf () devuelve un valor primitivo). Dado que la mayoría de los objetos no tienen el método ValueOf () disponible, utilizarán el método toString () para realizar el rastreo
Después de convertir el objeto al valor original, si una de las operaciones es una cadena, el otro operando también se convertirá en una cadena. Luego haga una concatenación de cadena.
De lo contrario, ambos operandos se convertirán en números (o NAN) y luego se agregarán.
Aquí hay algunos ejemplos
La copia del código es la siguiente:
1 + 2 // => 3 además
"1" + "2" // => "12" Conexión de cadena
"1" + 2 // => "12" Los números se convierten en cadenas y se concatenan
1 + {} // => "1 [objeto objeto]": el objeto se convierte en una cadena y luego se realiza la concatenación de cadena.
verdadero + true // => 2 El valor booleano se convierte en un número y se agrega
2 + nulo // => 2 nulo convertido a 0 y hacer suma
2 + Undefined // => Nan Conviertos indefinidos a NAN para suma
Finalmente, es importante tener en cuenta. Cuando la operación de signo más se usa en línea con las cadenas, se debe considerar el efecto de la adición en el orden de las operaciones. Es decir, el resultado de la operación depende de la orden de operación del operador, por ejemplo
La copia del código es la siguiente:
1 + 2 + "BMice" // => "3 BMice"
1 + (2 + "BMice") => "12bMice"
II. operador unario
El operador Unario actúa en un operando separado. y generar un nuevo valor. En JavaScript, los operadores Unary tienen una alta prioridad y están todos combinados. Esta sección describe los operadores unarios (+,-, ++ y-), y cuando es necesario, convierten las operaciones en números. Cabe señalar que + es un operador unario y también es un operador binario.
Adición de un Yuan+
El operador de adición Unario convierte el número de operando en un número (o NAN) y devuelve el número convertido. Si el operando en sí es un número, entonces el número se devuelve directamente.
Resta de una yuan-
Cuando el signo - es un operador unario, convertirá el operando en un número según sea necesario, y luego cambiará el símbolo del resultado de la operación.
Incremento ++
Incrementa el operador "++" para incrementar (+1) el operando, y el operando es un lvalue (variable, elemento de matriz u atributo de objeto). El operador convierte los operandos en números. Luego agregue 1 al número y reasigne el valor después de agregar 1 a la variable, elemento matricial u atributo de objeto.
La operación de incremento ++ devuelve el valor dependiente de su posición en el operando.
Cuando el operador está antes del número de operando, se llama operador "preincremento", que calcula incrementalmente el operando y devuelve el valor calculado.
Cuando el operador está después del operando, se llama operador "posterior al incremento". Realiza cálculos incrementales en el operando, pero devuelve el valor sin hundimiento que se utiliza para los cálculos incrementales. como
var i = 1, j = ++ i // Los valores de I y J son 2
var i = 1, j = i ++; // i es 2, j es 1
Cabe señalar que la suma de ++ x = x+1 es exactamente la misma. El operador "++" nunca realiza operaciones de concatenación de cadenas. Siempre convertirá el operando en un número y lo aumentará por 1. Si x es la cadena "1", el resultado de ++ x es el número 2, y x+1 es la cadena "11"
Las operaciones decrecientes e incrementadas son las mismas, lo que convierte los operandos en una matriz y luego resta por 1.
iii. bit operador
El operador de bits puede realizar operaciones de bit de nivel inferior en datos binarios representados por números. Aunque no son operaciones matemáticas puras tradicionales, también se clasifican aquí como operadores aritméticos porque actúan sobre operaciones de tipos numéricos y números de retorno. Estos operadores no son comunes en JavaScript. (No se describe aquí, use Baidu para más detalles ~-~)
9. Expresiones relacionales
Esta sección describe los operadores de relaciones de JavaScript. Los operadores relacionales se utilizan para probar la relación entre dos valores (igualdad, menos o "atributos") y devolver verdadero y falso según si la relación existe. Las expresiones relacionales siempre devuelven un valor booleano y, por lo general, usan expresiones relacionales en si o para declaraciones (Capítulo 5) para controlar el proceso de ejecución del programa.
Las próximas secciones hablarán sobre igualdad y operaciones desiguales, operadores de comparación y los otros dos caracteres de relación en JavaScript en e instancia de
I igualdad y operadores desiguales
Los operadores "==" y "===" se utilizan para comparar si dos valores son iguales, y los dos operadores permiten operadores de cualquier tipo. Devuelve verdadero si es igual, de lo contrario regresa falso. "===" también se llama el estricto operador de igualdad (a veces llamado operador de identidad), que se utiliza para detectar si dos operandos son estrictamente iguales. El operador "==" se llama operador de igualdad. Se usa para detectar si dos operandos son iguales. La definición de igualdad aquí es suelta y permite la conversión de tipo.
JavaScript admite los operadores "=", "==", "===", debe comprender las diferencias entre los operadores (asignación, igualdad, identidad). Y tenga cuidado al programar. Para reducir la confusión, "=" "debe llamarse" get o asignar "," == "" debe llamarse "igual", y "===" debe llamarse "estrictamente igual".
Las reglas de los operadores "! =" Y "! ==" son "==", el inverso del operador "===" y "!" es un no operador booleano. Llamamos "! =", "! ==" desigual y no estrictamente igual.
La comparación de los objetos JavaScript es una comparación de referencias, no una comparación de valores. Los objetos y ellos mismos son iguales, pero no son iguales a las personas y los objetos. Si dos objetos tienen el mismo número de atributos, los mismos nombres y valores de atributos, todavía son desiguales. Los elementos de la matriz en la posición correspondiente son iguales y dos matrices también son desiguales.
El operador de igualdad estricto "===" calcula primero el valor del operando y luego compare estos dos valores. No hay conversión en el proceso de comparación.
Si los dos tipos de valor no quieren ser los mismos, no son iguales
Si ambos valores son nulos o indefinidos, no son iguales
Si ambos valores son booleanos verdaderos o falsos, son iguales
Si uno de los valores es Nan, o ambos son Nan, no son iguales, y Nan y otros valores no son iguales, incluido sí mismo.
Si dos valores son números y son iguales, son iguales. Si un valor es 0 y un valor es -0, también es igual.
Si los dos valores son cadenas y los números de 16 dígitos (ver Capítulo 3, 2) contenidos en los bits correspondientes son exactamente iguales, son iguales. Si su longitud o contenido es diferente, no son iguales. Las dos cadenas pueden tener exactamente la misma función y los caracteres que se muestran son los mismos, pero tienen valores de 16 bits que no están codificados. JavaScript no realiza conversiones estándar en Unicode, por lo que tales cadenas no son iguales en comparación con los operadores "===" y "==". String.localecompare () en la tercera parte proporciona otra forma de comparar cadenas.
Si dos valores de referencia apuntan al mismo objeto, matriz o función, son iguales. Si apuntan a diferentes objetos, son desigualdad, aunque los dos objetos tienen exactamente las mismas propiedades.
El operador de igualdad "==" es similar al operador de identidad, pero el operador de igualdad no se compara estrictamente. Si los dos números no son del mismo tipo, el operador de igualdad intenta hacer algún tipo de conversión y luego se compara.
Si las dos operaciones son las mismas, las reglas de comparación para los operadores de igualdad anteriores son las mismas. Si es estrictamente igual, entonces los resultados de la comparación son iguales. Si no son estrictamente iguales, los resultados de la comparación no son iguales.
Si los dos tipos de operación son diferentes, el operador igual "==" también los considerará igual. La detección de la igualdad seguirá las siguientes reglas y conversiones de tipo:
Si un tipo es nulo y deje que el otro sea indefinido, es igual
Si un valor es un número y el otro es una cadena, convierta la cadena en un número primero y luego use el valor convertido para comparar.
Si un valor es verdadero, se convierte a 1 y luego se compara. Si un valor es falso, se convierte a 0 y se compara.
Si un valor es un objeto y el otro es un número o una cadena, use las reglas de conversión del método en el Capítulo 3, Sección 8, 3 para convertir el objeto al valor original y luego compararlo. El objeto se convierte en el valor original a través del método toString () o el método valueOf (). Las clases incorporadas en el núcleo del idioma JavaScript primero intentan usar valuef () y luego intentan usar toString (). Además de la clase de fecha, la clase de fecha solo se puede convertir a través de toString (). Los objetos que no están en el núcleo del lenguaje JavaScript se convierten en valores originales a través de métodos definidos en la implementación.
Las comparaciones entre otros tipos no son iguales
Aquí hay un pequeño ejemplo de igual juicio
"1" == Verdadero
El resultado de esta expresión es verdadero, lo que indica que los resultados de comparación de tipos de valores completamente diferentes son iguales. El valor booleano es verdadero primero convertido al número 1 y luego se realiza la comparación. A continuación, la cadena "1" también se convierte al número 1, porque los valores de los dos números son iguales, por lo que el resultado es verdadero.
II. Operador de comparación
Menos de (<)
Si el primer operando es más pequeño que el segundo operando, el resultado de la operación "<" es verdadero, de lo contrario es falso
Menos de o igual a (<=)
Mayor que (>)
Mayor o igual a (> =)
.... (sin introducción detallada al significado)
Los operandos del operador de comparación pueden ser de cualquier tipo. Sin embargo, solo los números y las cadenas realmente pueden realizar operadores de comparación, por lo que aquellos operandos que no son números y cadenas serán convertidos de tipo. Las reglas de conversión de tipo son las siguientes:
Si el operando es un objeto, se convertirá en el valor original de acuerdo con las reglas de conversión descritas en la Sección 3, Sección 8, 3: If ValueOf () devuelve un valor primitivo, luego use este valor original directamente. De lo contrario, use el resultado de conversión de toString () para comparar.
Después de convertir al valor original, si ambos operandos son cadenas, las dos cadenas se compararán en el orden del alfabeto. El "orden del alfabeto" mencionado aquí es el orden de índice de los caracteres Unicode de 16 bits que componen las dos cuerdas.
Después de que el objeto se convierte al valor original, si al menos un operando no es una cadena, ambos operandos compararán los valores de los números. 0 y -0 son iguales. Cualquier otro número en la pared de Infinty es grande (excepto Infinty en sí mismo), -infinty es más pequeño que cualquier número (excepto en sí mismo). Si un operando (o convertido) es nan, el carácter de comparación siempre devuelve falso
Para los operadores numéricos y de cadena, el comportamiento del operador de signo más es diferente del operador de comparación. El primero prefiere cadenas y realiza operaciones de concatenación de cadenas si uno de sus operandos es una cadena. Los operadores comparativos prefieren los números solo cuando ambos operandos son cadenas de cadenas. Solo entonces se realizará la comparación de cadenas.
La copia del código es la siguiente:
1 + 2 // => 3 además, el resultado es 3
"1" + "2" // Connect String, el resultado es "12"
"1" + 2 // Connect String, 2 se convierte en "2", el resultado es "12"
11 <3 // La comparación de números, el resultado es verdadero
"11" <"3" // Comparación de soporte, el resultado es verdadero
"11" <3 // comparación de números, "11" se convierte en 11, y el resultado es verdadero
"One" <3 // comparación de números ", uno" se convierte en NAN, y el resultado es falso
Finalmente, debe tenerse en cuenta que al juzgar la igualdad, los operadores "<=" y "> =" no confían en el operador de igualdad y las estrictas reglas de comparación de operaciones de igualdad. Por el contrario, el operador ZHI que es menor o igual a lo mismo es simplemente "no mayor que", mientras que la operación que es mayor o igual que solo es "no menor que". Con solo una excepción, cuando el operando (después de convertirse) es NAN, los 4 operadores de comparación devolverán Fasle.
iii.in operador
El operador en el operador quiere que su operando izquierdo sea una cadena o se puede convertir a una cadena, y espera que sea un objeto a la derecha. Si el objeto a la derecha tiene un nombre de atributo llamado valor de operando izquierdo, la expresión devuelve verdaderas. Por ejemplo
La copia del código es la siguiente:
Var Point = {
x: 1,
Y: 1
} // Defina un objeto
"x" en el punto // => Verdadero El objeto tiene una propiedad llamada x
"Z" en el punto // => Falso El objeto no tiene el atributo de nombre Z
"ToString" en el punto // => El objeto verdadero hereda el método de tostración
VAR Data = [7, 8, 8]
"0" en datos // => Verdadero La matriz contiene 0
1 en datos // => Número de conversión verdadero en cadena
3 en datos // => fase No hay elemento con un índice de 3
iiii.instance de operador
La instancia del operador desea que el operador izquierdo sea un objeto y el operando derecho indica la clase del objeto. Si el objeto a la izquierda es una instancia de la clase a la derecha, la expresión devuelve verdaderas; Es responsable de devolver falso. El Capítulo 9 hablará de ello. Las clases de objetos JavaScript se definen inicializando sus constructores. De esta manera, el operando correcto de instanciaf debería ser una función. Por ejemplo:
La copia del código es la siguiente:
var d = nueva fecha (); // Construye un nuevo objeto
d instancia de fecha; //The result of the calculation is true, d is created by Date()
d instanceof Object //计算结果为true ,所有的对象都是Object的实例
d instanceof Number //计算结果为false,d不是一个Number对象
var a = [1,2,3] //数组直接量创建数组
a instanceof Array //计算结果true a为数组
a instanceof Object //true 所有的数组都是对象
a instanceof RegExp //fasle 数组不是正则表达式
需要注意的是,所有对象都是Object的实例。当通过instanceof盘对一个对象是否为一个类的实例的时候,这个判断也叫“父类”(superclass)的检测,如果instanceof的左侧操作对象不是对象的话,instanceof返回false。如果右侧操作不是函数,则抛出类型错误的异常。
为了理解instanceof运算符是如何工作的,必须首先理解“原型类”(prototype chain),原型链作为javascript的继承机制,将在6章2节2小节详细描述。
为了计算表达式o instanceof f ,javascript笔仙首先计算f.prototyoe,然后在原型链中查询o,如果找到,那么o是f(或者f的父类)的一个实例,那么返回true。反之false
10.逻辑表达式
逻辑运算符"&&"、“||”、“!”是对操作进行布尔算术运算,经常和关系运算符一起配合使用,逻辑运算符将多个关系表达式组合起来组成一个更复杂的表达式。
i. Logic and
"&&"运算符可以从三个不同的层次进行理解。最简单一层理解是,当操作数都是布尔值是,“&&”对两个布尔值执行布尔与(AND)操作,只有在第一个操作数和第二个操作数都是true的时候,它才返回true.如果其中有一个操作数为false.则它返回false.
"&&"长用来连接两个关系表达式
x == 0 && y == 0; //只有在x和y都是0时,才返回true
关系表达式总是返回true或false,因此当这样使用的时候,“&&”本身也返回true或false。关系运算符的优先级要比"&&"(和“||”)要高,因此类似这种表达式可以放心地书写,而不用补充园括号。
"&&"操作数并不一定是布尔值,回想一下,有些值是可以当做“真值”和“假值”的。(如3章3节,假值是:false null undefined 0 -0 NaN和"",所有和其它的值包括所有的对象都是真值)。对“&&”第二层理解是,“&&”是可以对真值和假值进行布尔与(AND)操作。如果两个操作数都是真值的,则那么返回一个真值;否则,至少一个操作数是假值的。javascript中在任何使用布尔值的地方的时候,表达式语句都会将其当做真值或假值来对待,因此实际上“&&”并不总是返回true和false.但也并无大碍。
需要注意的是,上文提到了运算符返回“真值”和“假值”,但并没说说明这个“真值”或者“假值”到底是什么值,为此我们深入讨论对“&&”第三层的理解。运算符首先计算左操作数的值,即首先计算“&&”左侧的表达式,如果计算结果是假值,那么整个表达式的结果一定是假值,因此“&&”这时简单的返回左操作的值,而并不会对右边的操作数进行计算。
La copia del código es la siguiente:
var o = {
x: 1
};
var p = null;
o && ox; //=>1 : 1:0是真值,因此返回值是ox
p && px //= null :p是假值,因此将其返回,而并不计算px
这对于理解“&&”可能不计算右操作数的情况至关重要,在上述代码中,变量P的值是null,而如果计算px的话则会抛出一个异常错误,因此,只有p为真值(不能是null或undefined)的情况下才计算px
"&&"的行为有时候被称为“短路”(short circuiting),我们经常能看到很多代码利用了这一也行来有条件的执行代码。例如下面的两条代码是等价的
La copia del código es la siguiente:
if (a == b) stop(); //只有a==b时才能调运stop()
(a == b) && stop(); //同上
一般来讲,当“&&”右侧的表达式具有副作用的时候(赋值,递增,递减和函数调用表达式)要格外小心。因为这些带有副作用的表达式的执行时候,依赖于左操作鼠的计算结果。
尽管“&&”可以按照第二层和第三层的理解进行一些复杂的表达式运算,但大多数的情况下,“&&”仅用来对真值和假值的做布尔计算。
ii.逻辑或(||)
"||"运算符对两个操作数做布尔或(OR)运算。如果其中一个为真值,则返回真值,两个操作数都为假值,返回假值。
尽管“||”运算符大多情况下只是做简单的布尔或(OR)运算,和“&&”一样,也具备一些更复杂的行为,它首先计算第一个操作数的值,也就是说回首先计算左侧的表达式,如果计算结果为真,则返回真值,否则,再计算第二个值。
和“&&”一样,用于应该避免右操作数包含一些具有副作用的表达式,除非你目地明确在右侧使用带副作用的表达式,而有可能不会计算右侧的表达式。
这个运算符最常用的方式是用来从一组备选的表达中选取第一个真值的表达式。
La copia del código es la siguiente:
//如果max_width已经定义了,则直接使用它。赋值在preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量。
var max =max_width || preferences.max_windth || 500;
这种贯用法通常在函数体内,用来给参数提供默认值。
La copia del código es la siguiente:
//将o成功的属性复制到p中,并返回p
function copy(o, p) {
p = p || {}; //如果向参数p没有传入任何对象,则使用一个新创建对象。
//函数体内的主逻辑
iii.逻辑非(!)
El "!" operator is a unary operator that is placed before a separate operand. Its purpose is to invert the boolean value of the operand.
Unlike the "&&" and "||" operators, the "!" operator first converts its operands into a Boolean value (see the Rules in Chapter 3), and then inverses the Boolean value. Eso es, "!" always returns true and false. Furthermore, the Boolean value of a value can be obtained by using two logical non-operations: (!!x, refer to Section 8, Section 2, Chapter 3)
“!”具有很高的优先级,并且和操作数紧密的绑在一起,如果希望对p && q,则需要园括号!(p && q)。如下代码:
La copia del código es la siguiente:
!(p && q) === !p || !q
!(p || q) === !p && !q
对于p和q取任何值,这两个表达式永远成立。
11.赋值表达式
javascript使用"="运算符给变量或者属性来赋值,例如:
La copia del código es la siguiente:
i = 0 //将变量i设置为0
ox = 1 //将对象o的属性x 设置为1
“=”运算符希望它的左操作数为一个左值:一个变量或者对象属性(或数组元素),它的右操作鼠可以是任意的类型的任意值。赋值表达式的值就是右操作数的值。赋值表达式的副作用是,右操作数的值赋值给左侧的变量或对象属性。这样的话,后续对这个变量和对象的属性的引用都将得到这个值。
尽管赋值表达式的值非常简单,但有时候会看到一些复杂表达式包含赋值表达式的情况。例如:将赋值和检测操作放在一个表达式中:
La copia del código es la siguiente:
(a = b) == 0
如果这样的话,应该清楚地知道"="和"=="区别!,需要注意的是,“=”有非常低的优先级,通常在一个较长的表达式中用到一条赋值语句时,需要补充园括号以保障正确的运算顺序。
赋值操作符的结合性是从右至左,也就是说,一个表达式中出现了多个赋值运算符,运算顺序也从右至左,因此,可以通过以下方式对多个变量赋值。
La copia del código es la siguiente:
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包含具有副作用的表达式(比如函数调用和赋值操作)的时候,两者才不等价。如下两个表达式不等价
La copia del código es la siguiente:
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()函数时,它总共是在它的上下文作用域内支线。其它间接调用则使用全局函数为其上下文作用域。并且无法读、写、定义局部变量和函数。下面有一段代码实例:
La copia del código es la siguiente:
var geval = eval; //使用别名调用eval将是全局eval
var x = "global",
y = "global"; //两个全局变量
function f() { //函数内执行的局部eval
var x = "local" //定于局部变量
eval("x += 'changed';"); //直接eval更改了局部变量的
regresar x; //Return the changed local variable
}
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. Conditional operator (?:)
The conditional operator is the only ternary operator in javascript. Usually this operator is written as "?:". This operator has the third operand, the first operand is before "?", and the second operand is between "?" y ":". The third operand is long after ":", e.g.
x > 0 ? x : -x; //求x的绝对值
条件运算符的操作数可以是任意类型。第一个操作数当成布尔值,如果它是真值,那么将计算第二个操作数,并返回计算结果。赋值如果第一个值操作数是假值,那么将计算第三个操作数。并返回计算结果。第二个和第三个操作数总会计算其中之一。不可能两者同时进行。其实使用if语句也达到同样的效果(5.4.1),“?:”运算符只是提供了一种简写形式。这里是一个"?:"的典型使用场景,判断一个变量是否有定义,如果有定义则使用它,如果无定义,则使用一个默认值。
La copia del código es la siguiente:
grett = "hello" + (username ? username : "three");
和以下的代码是等价的,但上面的更加简洁
La copia del código es la siguiente:
grett = "hello";
if (username)
grett += username;
demás
grett + "three"
ii.typeof()运算符
typeof是一元运算符,放在单个操作数前面,操作数可以是任何类型,返回值表示操作类型的一个字符串。
La copia del código es la siguiente:
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也是具有副作用的。它是用来做删除操作的。不是用来返回一个值的。
La copia del código es la siguiente:
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删除还有严格模式下的一些情况,需要学习的人自己试验,这里给一些例子。
La copia del código es la siguiente:
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"来代替
incógnita; // An error occurred during runtime, no x is defined
6章第三节还有关于delete的讨论。
iii.void运算符。
void是一元运算符,在出现操作数之前,操作数可以是任何类型。这个运算符并不是经常使用:操作数会照常计算,但会忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用时使用void来程序更有意义。
这个最常用的带客户端url.在url写带有副作用的表达式,而void则让浏览器不显示在这个表达式的运算结果。
La copia del código es la siguiente:
<a href="javascript:void window.open();">new</a>
iiii.逗号运算符。(,)
逗号运算符是二元运算符,它的操作数可以是任意类型。它首先计算左操作数,然后计算右操作数。
La copia del código es la siguiente:
i = 0, j = 1, k = 2;
它和下面的代码基本上等价的
i = 0; j = 1; k = 2;
总是会计算左侧的表达式,但计算结果忽略掉,也就是说,只有左侧表达式具有副作用,才会使用逗号运算让代码变得更通畅。逗号运算符最常用的场景是for循环中,这个for循环通常有多个循环变量。
La copia del código es la siguiente:
//for循环中的第一个逗号是var语句的一部分
//第二个逗号是逗号运算符
//它将两个表达式(i++和j++)放在一条(for循环中)语句中
for (var i = 0, j = 10; i < j; i++, j--);
console.log(i + j);