本文内容讲述JS里最基本的知识:变量 和 操作符
变量的声明
变量的声明有三种方法: var
, let
, const
- var 声明一个变量,将其初始化成一个值,不支持块级作用域,存在变量提升。注意:使用
var
操作符定义的变量将成为定义该变量的作用域中的局部变量,也就是说,如果在函数中使用var
定义一个变量,在函数执行完毕生命周期结束时这个局部变量也会被销毁。
|
特殊的一点: 在函数内部声明变量如果不使用var
操作符的话这个变量会被创建成一个全局变量。
|
- let 声明一个块级作用域变量, 可以将其初始化成一个值。在同一作用域中不允许重复声明,存在暂存死区(不支持变量提升)。
|
- const 声明的标识符绑定的值不可以再次改变,其他行为和let一样
|
|
严格模式:use strict
下,不声明进行使用会报错:
|
数据类型
ECMAScript中有6种简单数据类型,Undefined, Null, Boolean, Number, String, Symbol. 一种复杂数据类型Object(Function).
typeof操作符
用来检测给定变量的数据类型:
|
PITFALL ALERT:
- 对于未定义和未初始化的变量,typeof对其的检测结果都是
undefined
,这说明了显式初始化变量的重要性,以使我们可以分辨一个变量是否已经被声明。
|
- 因为基本包装类型的存在,依赖typeof进行类型检测并不可靠:(PS:基本包装类型从属于引用类型,在之后将介绍,期间还会有一个小trick,留意哦)
|
- 可靠的检测方法
|
Undefined类型
Undefined类型只有一个值: undefined
,其他内容上面已经带着说了一下。
Null类型
它是第二个只有一个值的类型,它可以被看做javascript一切对象的起源,后面讲原型的时候会讲到。null值表示一个空对象指针,这也是为什么检测null用typeof会返回obejct的原因。 如果生命了以后对象是为了以后保存一个对象,那么可以显式的将其初始化为null而不是其他值。
|
undefined其实派生自null.
Boolean类型
两个值: ture
and false
.如果想要将其他类型的值转化为boolean类型,可以使用转型函数Boolean(); 在if语句中,括号里的值也会被调用Boolean()进行转型,转型结果见下面falsy value.
|
另外我们也可以使用!!
让一个值转化为boolean类型:
|
falsy value
所谓falsy value就是这些值在进行转型时会被转化成false的值:
- false`
- “”(空字符串)
- 0 和 -0 , NaN
- null
- undefined
而除此以外,非空字符串,非0数字值,包括Infinity,任何对象,都能被转化为true.
Number类型
整数范围:-2^53 - 2^53, Number类型具有不同进制数,ECMA-262定义了不同的数值字面量格式:
- 八进制第一位必须为0,然后是八进制数字序列(0-7),如果字面值中的数值超出了范围,前导的0将会被忽略,后边的数值将被当做十进制数值解析。
- 十六进制前两位必须是0x, 后跟任何十六进制数字(0-9,A-F), A-F字母可以大写也可以小写。
|
进行算术计算时,所有以八进制和十六进制表示的数值最终都将被转化成十进制,也就是说计算使用十进制。
|
浮点值
- 内存占用为整数的两倍,所以JS会抓住时机将其转化为整数,比如小数点后没有任何数字时,它就会被保存为整数:
var a = 1.;
, 如果浮点值本身表示的就是整数,也会被转化成整数:var b = 11.0;
- JS的浮点数计算使用基于IEEE754数值的浮点计算:
0.1 + 0.2 !== 0.3
- 可以使用科学计数法:
var floatNum = 3.12e7
,等于31250000. Number.MIN_VALUE
: 5e-324Number.MAX_VALUE
: 1.7976931348623157e+308- 如果一个数值超越了数值范围,会被转化成
Infinity
(带正负号),可以用isFinite()判断一个值是否有穷。 NaN
,任何涉及NaN
的值都会返回NaN
, 不和任何值相等,包括自己,所以有一个isNaN()函数用来判断它,接受一个值,使用Number()转型函数将其转换成数字,然后判断其是不是NaN
.- 如果传入对象,会先调用valueOf()方法,如果不能转化为数值,就调用toString()方法,再返回测试值
数值转换
Number()
, parseInt()
, parseFloat()
, Number可以把任何数据类型转型成数值,后面两个方法专注于将字符串转化成数值。
- 如果是Boolean值,true和false分别别转化成1和0
- 如果是数字,简单的传入和返回
- 如果是null,返回0
- 如果是undefined,返回NaN
- 如果是对象,调用对象的valueOf方法,然后按前面的规则转化,如果结果是NaN,则调用toString方法,再按照前面的方法转化。
|
parseInt(): 它会忽略传入字符串前面的空格,直到找到第一个非空格字符串,如果第一个字符不是数字字符,或者符号,返回NaN
。如果第一个字符是数字,则继续解析,直到解析完所有字符或者遇到非数字字符则停下来。
|
在ECMAScipt 5 JavaScript引擎中,已经不支持对八进制的解析,所以可以传入第二个参数进行制定制式解析。
|
parseFloat(): 始终会忽略前导的0,只解析十进制数值,而且如果转化后的小数满足转化成整数的原则的话,会自动转化为整数: ‘1.’=> 1, ‘11.0’=>11
暂时更到这里,明天继续。
String类型
表示
单引号or双引号,前后统一。 单引号使用较多,见如下情况:
|
转义
/n
:换行, \'
or \"
单引号,双引号。 \unnnn
以十六进制代码nnnn代表一个Unicode字符.
任何字符串的长度都可以通过访问length
属性取得,要注意的是如果字符串包含双字节字符,那么length
可能不会精确的返回字符串中的字符数目。
|
不可变
字符串一旦创建,它们的值就不能改变,我们所见到的变量保存字符串的重新赋值,其实是已经销毁了以前的字符串.
|
转换
第一种方式: toString()
|
第二种方式: 使用加号(+
)操作符,将某个值跟另一个字符串加在一起,就会将这个值转换为字符串。
|
包装类型
Boolean, Number, String也属于特殊的引用类型,它们同时也具有各自基本类型的特殊行为,在每读取一个基本类型值的时候,后台就会建立一个对应的基本包装类型
的对象(作为引用类型的由来),可以让我们调用一些方法来操作这些数据。
看个例子:
|
我们知道s1是一个字符串,那它理应属于原始类型数据,那我们又何从调用一个方法呢?其实在第二行代码后台访问s1的时候,会处于一种读取模式,即从内存中读取这个字符串的值,而在读取模式中,后台也会自动完成以下三个步骤:
- 创建String类型的一个实例。
- 在实例上调用指定的方法。
- 销毁这个实例。
可以看作是隐式执行了如下代码:
|
还记得我们之前说过,javascript的一切都是对象,这句话是没错的,就是因为存在对于基本类型的包装对象,只是我们很难明显的察觉到它。
我们也可以显式的调用String, Number, Boolean来创建一个基本包装类型的对象,但是这样的做法是不推荐的,因为这样让我们很难分清我们到底是在对于原始数据类型进行操作,还是对引用类型进行操作。所以不是绝对必要的情况下,还是使用字面量的形式创建。
我们也可以使用Object创建基本包装类型对象,而Object会自动识别传入值的类型而返回相应的基本包装类型的实例,见如下代码:
|
要注意的是,使用new调用基本类型的构造函数,与直接调用同名的转型函数是不一样的:
|
那么,对于基础类型和复杂类型,它们的区别是什么呢?
基础类型保存的是一个值,而复杂类型保存的是内存地址,通过访问内存地址,我们可以接触到里面的基础类型所保存的值。在传递时,基础类型直接传递值,而复杂类型直接传递内存地址,也就是我们所说的:引用。当我们使用引用传递时,通过变量访问这些地址,从而进行一些修改,无论这些引用地址被传递给多少个变量,通过其中任何一个进行修改,都会使堆内存中保存的对象发生相应变化。
|
JavaScript中的内存也分为栈内存和堆内存。一般来说,栈内存中存放的是存储对象的地址,而堆内存中存放的是存储对象的具体内容。对于原始类型的值而言,其地址和具体内容都存在与栈内存中;而基于引用类型的值,其地址存在栈内存,其具体内容存在堆内存中。堆内存与栈内存是有区别的,栈内存运行效率比堆内存高,空间相对推内存来说较小,反之则是堆内存的特点。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。
Object类型
它是一组数据和功能的集合,可以通过执行new操作符后跟要创建的对象类型的名称来创建。
|
它有一些属性和方法,我们会在后面的引用类型专题详细说:
- constructor: 保存着用于创建当前对象的函数
- hasOwnProperty(propertyName): 用于检查某个属性在当前对象的实例中而不是在实例的原型中,传入的参数必须是字符串形式。
- isPrototypeOf(object): 用于检查传入的对象是否是当前对象的原型。
- propertyIsEnumerable(propertyName): 用于检查给定的属性是否能够在for-in语句中被枚举出来。
- toLocaleString(): 返回对象的字符串表示,这个字符串跟执行环境的地区对应。
- toString()
- valueOf: 返回对象的字符串,数值或布尔表示,通常与toString的返回值相同,之前我们提到过如果使用Number进行转型时也会先调用valueOf方法。
|
操作符
一元操作符
|
布尔操作符
逻辑非
- 如果操作数是一个对象,返回false.
- 如果操作数是一个空字符串,返回true.
- 如果操作数是一个非空字符串,返回false.
- 如果操作数是数值0,返回true.
- 如果操作数是任意非0数值,返回false.
- 如果操作数是null,返回true.
- 如果操作数是NaN,返回true.
- 如果操作数是undefined,返回true.
|
逻辑与
|
逻辑或
|
||经常用来设置默认值:
|
加性操作符
PITFALL ALERT
|
减性操作符
|
关系操作符
|
相等操作符
非严格相等:
- 如果有一个操作数是布尔值,在比较相等性之前先将其转化为数值:
false
转换为0
,而true
转换成1
. - 如果一个操作数是字符,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
- 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf(),转化成基本类型值以后再去比较。 (转化成原始值)
- 如果二者都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作返回ture.
|
严格相等
|
|