表达式
原始表达式
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
运算符
网友评论