标签:结合 instance ... led def else bsp 变量赋值 地方
打开 Chrome 开发工具
Win
F12Mac
Command + Option + I输入代码、测试执行
var str = ‘evenyao‘
console.log(str)
JavaScript程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是一个语句。
语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句:
var a = 1 + 3;
这条语句先用var
命令,声明了变量a
,然后将1 + 3
的运算结果赋值给变量a
。
1 + 3
叫做表达式(expression),指一个为了得到返回值的计算式。语句和表达式的区别在于,前者主要为了进行某种操作,一般情况下不需要返回值;后者则是为了得到返回值,一定会返回一个值。
凡是JavaScript语言中预期为值的地方,都可以使用表达式。比如,赋值语句的等号右边,预期是一个值,因此可以放置各种表达式。一条语句可以包含多个表达式。
语句以分号结尾,一个分号就表示一个语句结束。多个语句可以写在一行内。
var a = 1 + 3 ; var b = ‘abc‘;
分号前面可以没有任何内容,JavaScript引擎将其视为空语句。
;;;
上面的代码就表示3个空语句。(关于分号的更多介绍,请看后文《代码风格》一节。)
表达式不需要分号结尾。一旦在表达式后面添加分号,则JavaScript引擎就将表达式视为语句,这样会产生一些没有任何意义的语句。
1 + 3;
‘abc‘;
上面两行语句有返回值,但是没有任何意义,因为只是返回一个单纯的值,没有任何其他操作。
变量是对“值”的引用,使用变量等同于引用一个值。每一个变量都有一个变量名。
var a = 1;
上面的代码先声明变量a
,然后在变量a
与数值1之间建立引用关系,也称为将数值1“赋值”给变量a
。以后,引用变量a
就会得到数值1。最前面的var
,是变量声明命令。它表示通知解释引擎,要创建一个变量a
。
变量的声明和赋值,是分开的两个步骤,上面的代码将它们合在了一起,实际的步骤是下面这样。
var a;
a = 1;
如果只是声明变量而没有赋值,则该变量的值是undefined
。undefined
是一个JavaScript关键字,表示“无定义”。
var a;
a // undefined
如果变量赋值的时候,忘了写var
命令,这条语句也是有效的。
var a = 1;
// 基本等同
a = 1;
但是,不写var
的做法,不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var
命令声明变量。
严格地说,
var a = 1
与a = 1
,这两条语句的效果不完全一样,主要体现在delete
命令无法删除前者。不过,绝大多数情况下,这种差异是可以忽略的。
如果一个变量没有声明就直接使用,JavaScript会报错,告诉你变量未定义。
x
// ReferenceError: x is not defined
上面代码直接使用变量x
,系统就报错,告诉你变量x
没有声明。
可以在同一条var
命令中声明多个变量。
var a, b;
JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,可以赋予各种类型的值。
var a = 1;
a = ‘hello‘;
上面代码中,变量a
起先被赋值为一个数值,后来又被重新赋值为一个字符串。第二次赋值的时候,因为变量a
已经存在,所以不需要使用var
命令。
如果使用var
重新声明一个已经存在的变量,是无效的。
var x = 1;
var x;
x // 1
上面代码中,变量x
声明了两次,第二次声明是无效的。
但是,如果第二次声明的同时还赋值了,则会覆盖掉前面的值。
var x = 1;
var x = 2;
// 等同于
var x = 1;
var x;
x = 2;
JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
console.log(a);
var a = 1;
上面代码首先使用console.log
方法,在控制台(console)显示变量a的值。这时变量a
还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。
var a;
console.log(a);
a = 1;
最后的结果是显示undefined
,表示变量a
已声明,但还未赋值。
请注意,变量提升只对var
命令声明的变量有效,如果一个变量不是用var
命令声明的,就不会发生变量提升。
console.log(b);
b = 1;
上面的语句将会报错,提示“ReferenceError: b is not defined”,即变量b
未声明,这是因为b
不是用var
命令声明的,JavaScript引擎不会将其提升,而只是视为对顶层对象的b
属性的赋值。
标识符(identifier)是用来识别具体对象的一个名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript语言的标识符对大小写敏感,所以a
和A
是两个不同的标识符。
标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript引擎遇到非法标识符,就会报错。
简单说,标识符命名规则如下:
$
)和下划线(_
)。0-9
。下面这些都是合法的标识符。
arg0
_tmp
$elem
π
下面这些则是不合法的标识符。
1a // 第一个字符不能是数字
23 // 同上
*** // 标识符不能包含星号
a+b // 标识符不能包含加号
-d // 标识符不能包含减号或连词线
中文是合法的标识符,可以用作变量名。
var 临时变量 = 1;
JavaScript有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。
另外,还有三个词虽然不是保留字,但是因为具有特别含义,也不应该用作标识符:Infinity
、NaN
、undefined
。
源码中被JavaScript引擎忽略的部分就叫做注释,它的作用是对代码进行解释。Javascript提供两种注释:一种是单行注释,用//起头;另一种是多行注释,放在/* 和 */之间。
// 这是单行注释
/*
这是
多行
注释
*/
此外,由于历史上JavaScript兼容HTML代码的注释,所以<!--
和-->
也被视为单行注释。
x = 1; <!-- x = 2;
--> x = 3;
上面代码中,只有x = 1
会执行,其他的部分都被注释掉了。
需要注意的是,-->
只有在行首,才会被当成单行注释,否则就是一个运算符。
function countdown(n) {
while (n --> 0) console.log(n);
}
countdown(3)
// 2
// 1
// 0
上面代码中,n --> 0
实际上会当作n-- > 0
,因此输出2、1、0。
JavaScript使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。
与大多数编程语言不一样,JavaScript的区块不构成单独的作用域(scope)。也就是说,区块中的变量与区块外的变量,属于同一个作用域。
{
var a = 1;
}
a // 1
上面代码在区块内部,声明并赋值了变量a
,然后在区块外部,变量a
依然有效,这说明区块不构成单独的作用域,与不使用区块的情况没有任何区别。所以,单独使用的区块在JavaScript中意义不大,很少出现。区块往往用来构成其他更复杂的语法结构,比如for
、if
、while
、function
等。
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了第七种 Symbol 类型的值)
true
(真)和false
(假)两个特定值undefined
:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值null
:表示无值,即此处的值就是“无”的状态。通常,我们将数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。而将对象称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined
和null
,一般将它们看成两个特殊值。
对象又可以分成三个子类型。
JavaScript有三种方法,可以确定一个值到底是什么类型。
typeof
运算符instanceof
运算符Object.prototype.toString
方法instanceof
运算符和Object.prototype.toString
方法,将在后文相关章节介绍。这里着重介绍typeof
运算符。
typeof
运算符可以返回一个值的数据类型,可能有以下结果。
(1)原始类型
数值、字符串、布尔值分别返回number
、string
、boolean
。
typeof 123 // "number"
typeof ‘123‘ // "string"
typeof false // "boolean"
(2)函数
函数返回function
。
function f() {}
typeof f
// "function"
(3)undefined
undefined
返回undefined
。
typeof undefined
// "undefined"
利用这一点,typeof可以用来检查一个没有声明的变量,而不报错。
v
// ReferenceError: v is not defined
typeof v
// "undefined"
上面代码中,变量v
没有用var
命令声明,直接使用就会报错。但是,放在typeof
后面,就不报错了,而是返回undefined
。
实际编程中,这个特点通常用在判断语句。
// 错误的写法
if (v) {
// ...
}
// ReferenceError: v is not defined
// 正确的写法
if (typeof v === "undefined") {
// ...
}
(4)其他
除此以外,其他情况都返回object
。
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
从上面代码可以看到,空数组([]
)的类型也是object
,这表示在JavaScript内部,数组本质上只是一种特殊的对象。
既然typeof
对数组(array)和对象(object)的显示结果都是object
,那么怎么区分它们呢?instanceof
运算符可以做到。
var o = {};
var a = [];
o instanceof Array // false
a instanceof Array // true
instanceof
后续讲解。
布尔值代表“真”和“假”两个状态。“真”用关键字true
表示,“假”用关键字false
表示。布尔值只有这两个值。
下列运算符会返回布尔值:
&&
(And),||
(Or)!
(Not)===
,!==
,==
,!=
>
,>=
,<
,<=
如果JavaScript预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false
,其他值都视为true
。
undefined
null
false
0
NaN
""
或‘‘
(空字符串)布尔值往往用于程序流程的控制,请看一个例子。
if (‘‘) {
console.log(true);
}
// 没有任何输出
上面代码的if
命令后面的判断条件,预期应该是一个布尔值,所以JavaScript自动将空字符串,转为布尔值false
,导致程序不会进入代码块,所以没有任何输出。
需要特别注意的是,空数组([]
)和空对象({}
)对应的布尔值,都是true
。
if ([]) {
console.log(true);
}
// true
if ({}) {
console.log(true);
}
// true
更多关于数据类型转换的介绍,参见《数据类型转换》一节。
JavaScript中运算符主要用于连接简单表达式,组成一个复杂的表达式。常见的有算数表达式、比较表达式、逻辑表达式、赋值表达式等,也有单目运算符,指操作原始表达式。大多数运算符都由标点符号组成(+、>=、!),也有关键字表示的运算符,如typeof、delete、instanceof等。
一些运算符可以作用于任何数据类型(typeof),但大部分操作符希望操作数是特定的类型,而且大部分操作符会计算出(我们也常说返回)一个特定类型的值(typeof返回的全是string)。在JavaScript中运算符通常会根据需要对操作数进行类型转换,乘法操作符希望操作数是数字,但是 "3" * "5"
也是合法的,JavaScript会自动将其转换为数字计算,返回Number 15。
有些操作符对不同的数据类型有不同的含义,比如 +
console.log(2+4);//6
console.log("2"+"4");//"24"
console.log(2+"4");//"24"
console.log(2+new Date());//"2Mon Jan 20 2014 17:15:01 GMT+0800 (China Standard Time)"
console.log(+"4");//4
赋值运算符用于给变量赋值,最常见的赋值运算符,当然就是等号,表达式x=y
表示将y赋值给x。除此之外,JavaScript还提供其他11个赋值运算符。
x += y // 等同于 x = x + y
x -= y // 等同于 x = x - y
x *= y // 等同于 x = x * y
x /= y // 等同于 x = x / y
x %= y // 等同于 x = x % y
x >>= y // 等同于 x = x >> y
x <<= y // 等同于 x = x << y
x >>>= y // 等同于 x = x >>> y
x &= y // 等同于 x = x & y
x |= y // 等同于 x = x | y
x ^= y // 等同于 x = x ^ y
比较运算符比较两个值,然后返回一个布尔值,表示是否满足比较条件。JavaScript提供了8个比较运算符。
==
相等===
严格相等!=
不相等!==
严格不相等<
小于<=
小于或等于>
大于>=
大于或等于!
取反运算符&&
且运算符||
或运算符condition? true case : false case
三元条件运算符|
,表示两个二进制位中有一个为1,则结果为1,否则为0。&
,表示两个二进制位都为1,则结果为1,否则为0。~
,表示将一个二进制位变成相反值。ˆ
,表示两个二进制位中有且仅有一个为1时,结果为1,否则为0。<<
>>
>>>
在JavaScript中,圆括号是一种运算符,它有两种用法:如果把表达式放在圆括号之中,作用是求值;如果跟在函数的后面,作用是调用函数。
把表达式放在圆括号之中,将返回表达式的值。
void运算符的作用是执行一个表达式,然后返回undefined。
逗号运算符用于对两个表达式求值,并返回后一个表达式的值。
优先级什么意思大家都清楚,结合性是指多个具有同样优先级的运算符表达式中的运算顺序。有的运算符是左结合的,即运算从左到右执行,下面两个运算是一样的
w = x + y + z;
w = (x + y) + z;
有的运算符是右结合的
w = x = y = z;
w = (x = (y = z));
w = a: b: c ? d : e? f : g;
w = a? b : (c? d: (e? f : g));
运算符的优先级《JavaScript权威指南》中有个表阐述的很好(我去掉了位运算部分),其中R/L代表结合性是右结合还是左结合,num->num表示操作符期望的数据类型和计算结果类型,lval指左值
运算符 | 操作 | 结合性 | 类型 |
---|---|---|---|
++ | 自增 | R | lval->num |
-- | 自减 | R | lval->num |
- | 求反 | R | num->num |
+(一个操作数) | 转换为数字 | R | num->num |
~ | 按位求反 | R | int->int |
! | 逻辑非 | R | bool->bool |
delete | 删除属性 | R | lval->bool |
typeof | 检测数据类型 | R | any->str |
void | 返回undefined | R | any->undefined |
*、/、% | 乘、除、求余 | L | num,num->num |
+、- | 加、减 | L | num,num->num |
+ | 字符串拼接 | L | str,str->str |
<、<=、>、>= | 数字大小或字母表顺序 | L | num/str,num/str->bool |
instanceof | 对象类型 | L | obj,function->bool |
in | 测试属性是否存在 | L | str,obj->bool |
== | 判断相等 | L | any,any->bool |
!= | 判断不等 | L | any,any->bool |
=== | 判断恒等 | L | any,any->bool |
!== | 判断非恒等 | L | any,any->bool |
&& | 逻辑与 | L | any,any->any |
|| | 逻辑或 | L | any,any->any |
?: | 条件运算符 | R | bool,any,any->any |
=赋值 *=、/=、+=、-= | 赋值 运算且赋值 | R | lval,any->any |
, | 忽略第一个操作数,返回第二个操作数 | L | any,any->any |
有几个我们需要注意的地方
typeof的优先级相当的高,比加减乘除神马的都高,所以虽然是操作符,在在复杂表达式的时候我们还是习惯加括号,看个例子
typeof 2*3;//NaN
typeof (2*3);//"number"
typeof 2+3;// "number3"
++
、--
是右结合的操作符(优先级最高的几个都是右结合),而且比加减乘除优先级高。同时自增、自减运算符的运算数得是左值(可以放在赋值符号左边的值),而不能是常数
4++; //ReferenceError: Invalid left-hand side expression in postfix operation
var a=0,b=0;
a+++b;//0
a;//1,++优先级比+高,所以相当于(a++)+b
b;//0
赋值运算符的优先级相当的低
a = b == c; //等同于a = (b==c)
逻辑非!
也在优先级队列的前端,比加减乘除高,但逻辑与、逻辑或优先级很低,不如加减乘除
!2*0; //0, 等价于(!2)*0
一个关于逻辑运算符的有意思地方是其“短路”功能,相信大家都有所了解,但有些题目不那么单纯,会结合表达式计算值来考察
1 && 3;
1 && "foo" || 0;
1 || "foo" && 0
了解了逻辑运算符的“短路”特点,在知道原始表达式的“返回值”就是本身,题目就很简单了
我们知道可以使用==
或===
判断两个值的相等性,其中区别相信大家清楚,===
是严格意义的相等,只需注意NaN和NaN不等就行了。而使用==
的时候,javascript会帮我们做类型转换,造成一些匪夷所思的结果,那么使用==
的时候会在哪些情况下做类型转换,又会换成什么样子?
null==undefined;
NaN==NaN
"1"==true
标签:结合 instance ... led def else bsp 变量赋值 地方
原文地址:https://www.cnblogs.com/evenyao/p/9323906.html