表达式
原始表达式
1.23
"hello"
/pattern/
true
false
null
this
i
sum
undefined
对象和数组的初始化表达式
-
对象和数组初始化表达式 实际上是一个新创建的对象和数组,这些 初始化表达式 有时称做 对象直接量 和 数组直接量 。
{}
{ topic: "JavaScript", fat: true }
[]
[1 + 2, 3 + 4]
函数定义表达式
function plus1(x) { return x + 1; }
属性访问表达式
-
属性访问表达式 运算得到一个对象属性或一个数组元素的值。
var o = {x: 1, y: {z: 3}};
var a = [o, 4, [5, 6]];
o.x
o.y.z
o["x"]
a[1]
a[2]["1"]
a[0].x
调用表达式
-
调用表达式 分 函数调用 和 方法调用 两种, 函数调用 中的
this指的是全局对象,而 方法调用 的this则代表着 方法 的对象。在 ES 5 中,通过严格模式定义的函数调用中,this的值为undefined。
f(0)
Math.max(x, y, z)
a.sort()
对象创建表达式
-
对象创建表达式 创建一个对象并调用一个函数初始化新对象的属性。
new Object()
new Point(2, 3)
// 不需要传入任何参数给构造函数时,可以省略括号
new Object
new Date
运算符
- 大多数运算符都是符号,少数非符号的运算符有:
delete,typeof,void,instanceof,in。
-
JavaScript 总是严格按照从左至右的顺序来计算表达式。
算术运算符
基本算术运算符
加法算术运算符 —— +
- 加法既可以做数字运算,也可以做字符串连接操作。
- 加法计算规则:
- 两个都是数字:加法运算。
- 两个都是字符串:字符串连接操作。
- 一个是数字,一个是字符串:数字转化为字符串,字符串连接操作
- 一个是对象,另一个是字符串或数字,转换规则如下:
-
Date类对象会使用toString()转换为字符串。
- 除
Date类以外的其他对象会使用以下规则:
- 使用
valueOf()转换为数字。
- 若没有
valueOf(),则使用toString()转换为字符串。
- 若没有既没有
valueOf()也没有toString(),【Todo】。
- 完成上述转换后,会有三种情况:
- 两个操作数都是字符串:字符串连接操作。
- 两个操作数都是数字:加法运算。
- 一个数字,一个字符串:数字转换为字符串,进行字符串连接操作。
- 两个操作数都转换为数字或者
NaN,然后进行加法操作。
- 加法需要考虑结合性对运算顺序的影响:
1 + 2 + "blind mice" // => "3 blind mice"
其他算术运算符 —— -、*、/、%
- 操作数尝试转换为数字,若无法转化为数字就转化为
NaN值。
- 如果操作数或转换结果是
NaN值,运算结果也为NaN值。
-
JavaScript 的除法是浮点型的。
- 除数为
0或-0时,运算结果为Infinity或-Infinity。
-
0/0的结果是NaN。
-
%的操作数通常都是整数,但也适用于浮点数。
-
%运算结果的符号与第一个操作数相同。
一元算术运算符 —— +、-、++、--
位算术运算符 —— &、|、^、~、<<、>>、>>>
-
>>右移补零时,由操作数的符号相关。
-
>>>右移补零时,总是补0。
关系运算符
- 关系运算符根据关系是否存在返回
true或false。
- 关系运算符包括:
、、、、、、、、x。
相等与不等运算符 —— ==、===、!=、!==
-
==是相等运算符。
-
===是严格相等运算符,也称恒等运算符。
-
!=称做不相等,!==称做不严格相等。
-
!=和!==运算符的检测规则是==和!==的运算符的求反。
-
JavaScript 对象比较的是引用,而不是值。
-
===的比较过程没有任何类型转换,有以下重要的比较情况:
-
null === undefined返回false。
-
NaN === x或者NaN === NaN,返回false。(若x !== x返回true,则可以判断x为NaN)
-
0 === -0返回true。
- 如果两个字符串对应为上的16位数完全相等,则
==和===返回true,若两个字符串显示出来的字符完全一样,但是内部编码的16位数不一样,则==和===返回false。
- 如果两个引用指向同一个对象、数组或函数,则
===返回true,如果指向不同的对象、数组或函数,则===返回false,尽管两个对象、数组或函数具有完全一样的属性、元素或函数体。
-
==和===类似,但是==不严格,有以下重要的比较情况:
- 两个操作数的类型相同,则返回结果与
===一致。
- 如果两个操作数类型不同:
-
null == undefined返回true。
- 如果是布尔值,则先转换为数字再进行比较。
true转换为1,flase转换为0。
- 一个数字,一个字符串:字符串转换为数字,比较数字。
- 如果一个是对象,另一个是数字或字符串,则使用以下转换规则:
-
Date类对象会使用toString()转换为字符串。
- 除
Date类以外的其他对象会使用以下规则:
- 使用
valueOf()转换为数字。
- 若没有
valueOf(),则使用toString()转换为字符串。
- 若没有既没有
valueOf()也没有toString(),【Todo】。
- 完成上述转换后,会有三种情况:
- 两个操作数都是字符串:比较字符串。
- 两个操作数都是数字:比较数字。
- 一个数字,一个字符串:字符串转换为数字,比较数字。
- 对于其他不同类型的操作数,
==返回false。
比较运算符 —— <、>、<=、>=
- 比较操作符的操作数可能是任意类型,但是只有数字和字符串才能真正执行比较操作。
-
<=是>的取反,>=是<的取反,只有一个例外,操作数有NaN时,返回值为false。
- 比较规则:
- 两个都是数字:
-
0和-0是相等的。
-
Infinity比任何值(除了自身)以外都大。
-
-Infinity比任何值(除了自身)以外都小。
- 其中一个是
NaN的话,返回false。
- 两个都是字符串:比较两个由16位值组成的序列。注意Unicode定义的字符编码中文不是按照拼音顺序的,英文则是所有大写字母小于小写字母。可以采用
String.localCompare()解决问题。
- 一个是数字,一个是字符串:字符串转换为数字,比较数字。
- 转换规则如下:
- 如果操作数是对象,则按照如下转换规则:
-
Date类对象会使用toString()转换为字符串。
- 除
Date类以外的其他对象会使用以下规则:
- 使用
valueOf()转换为数字。
- 若没有
valueOf(),则使用toString()转换为字符串。
- 若没有既没有
valueOf()也没有toString(),【Todo】。
- 完成上述转换后,会有三种情况:
- 两个操作数都是字符串:比较字符串。
- 两个操作数都是数字:比较数字。
- 一个数字,一个字符串:字符串转换为数字,比较数字。
in运算符
- 左操作数是一个字符串或可以转换为字符串,右操作数是一个对象。
- 如果右操作数对象有一个名为左操作数的属性名,表达式返回
true。
var point = {x : 1, y : 1};
"x" in point // true
"z" in point // false
"toString" in point // true
var data = [7, 8, 9];
"0" in data // true
1 in data // true
3 in data // false
instanceof运算符
- 左操作数是对象,右操作数是标识类的函数。
- 如果左操作数不是对象,返回
false,如果右操作数不是函数,抛出一个 类型错误异常 。
var d = new Date()
d instanceof Date; // true
d instanceof Object; // true
d instanceof Number; // false
var a = [1, 2, 3];
a instanceof Array; // true
a instanceof Object; // true
a instanceof RegExp; // false
逻辑运算符 —— &&、||、!
赋值运算符 —— =、+=、-=等
- 带操作的赋值运算符有:
+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、|=、^=。
表达式计算 —— eval()
-
eval()只有一个参数,如果传入的参数不是字符串,它直接返回这个参数。
-
eval()如果参数是字符串,它会把字符串当作 JavaScript 代码编译,如果编译失败则抛出一个 语法错误异常 。如果编译成功,则开始执行这段代码。
-
eval()的返回值为这个字符串最后一个表达式或语句的值,如果最后一个表达式或语句没有值,则最终返回undefined。
- 如果执行的字符串抛出异常,这个异常会传递给
eval()。
-
eval()使用了调用它的变量作用域环境,如下代码示例:
x = 1;
eval("x = 2") // 改变局部变量x的值
- 如果在再最顶层代码中调用
eval(),当然它会作用于全局变量和全局函数。
- 以下代码是错误的:
var foo = function(a) {
eval(a);
};
foo("return; "); // eval()的上下文环境就是函数调用的环境,即全局环境,在全局上下文中使用return会报错
-
直接eval :直接调用
eval()。
-
间接eval :通过别名来间接调用
eval()。
-
ES3 :
-
直接eval :在调用它的上下文作用域中执行,也叫 局部eval() 。
-
间接eval :禁止使用 间接eval ,若使用会抛出一个 EvalError异常 。
-
ES5 :
-
直接eval :在调用它的上下文作用域中执行,也叫 局部eval() 。
-
间接eval :使用全局对象作为其上下文作用域,并且无法读、写、定义局部变量和函数,也叫 全局eval() 。
-
ES5 严格模式:
-
直接eval :可以查询和更改局部变量,但是不能定义新的变量或函数。
-
间接eval : 禁止使用 间接eval ,若使用会抛出一个 EvalError异常 。
var geval = eval;
var x = "global", y = "global";
function f() {
var x = "local";
eval("x += 'change';"); // 此x是局部x
return x;
}
function g() {
var y = "local";
geval("y += 'changed';"); // 此y是全局y
return y;
}
console.log(f(), x);
console.log(g(), y);
- 通常不用
eval(),如果真的要用,更可能是用 全局eval() 而不是 局部eval() 。
其他运算符
typeof()运算符
- 接受一个任意类型的操作数,返回一个表示操作数类型的字符串。
- 在
switch语句中非常有用。
| x |
typeof(x) |
| undefined |
"undefined" |
| null |
"object" |
| true或false |
"boolean" |
| 任意数字或NaN |
"number" |
| 任意字符串 |
"string" |
| 任意函数 |
"function" |
| 任意内置对象(非函数) |
"object" |
| 任意宿主对象 |
由编译器各自实现的字符串 |
delete运算符
-
delete用来删除对象的属性或者数组元素。
- 与 C++ 中的
delete完全不同。
-
delete删除数组元素后,数组长度依旧不变。
-
delete返回值:
- 若操作数不是左值,不进行任何操作并返回
true。
- 若操作数是左值,如果删除成功返回
true,删除失败返回false。
- 不能使用
delete删除的有:
- 内置核心和客户端属性。
- 使用
var声明的变量。
- 函数。
- 函数参数。
-
ES5 严格模式:非法的
delete会报错。
var o = {x : 1, y : 2};
delete o.x;
o.y = undefined
"x" in o // false
"y" in o // true
var a = [1, 2, 3];
delete a[2];
2 in a; // false
a.length // 3:依旧是3
void运算符