2-1 JavaScript 基础语法
2-1-1注释
关于注释的作用,这里就不用多说了。之所以书写注释,就是为了让阅读代码的人更加方便。拥 有良好注释的代码是专业程序员的标志,它让阅读我们代码的任何人(包括我们自己)能更加容易 的理解某一段代码的作用是什么。如果没有注释,往往在几周后,我们回过头来阅读自己写的代 码时会发现,自己都看不懂。
在JavaScript中,注释可以分为单行注释和多行注释。
单行注释如下:
//这是一个单行注释
多行注释如下:
/*
*
*这是_个较长的
*多行的注释
*
*/
不过,虽然说写注释是一个好习惯,这也不是意味着每一句代码都要写注释。往往我们是针对某 —个功能来书写一个注释说明,像下面这样的注释是毫无意义的
let i = 5;//将5赋值给:L变量
2-1-2语句
在JavaScript中,语句一般我们都会采用以分号结尾,每条语句独占一行的形式来书写代码。当 然,如果一条语句后面不添加分号,也不会报错,但是在进行代码压缩的时候可能会带来一些问 题。所以还是建议每条语句加上分号。
let i = 10;
console.log(i);//10
可以使用C语言的风格用一对大括号将多条语句组合到一个代码块里面。
let i = 10;
console.log(i);//10 }
2-1 -3标识符
所谓标识符,就是指用来标识某个实体的一个符号。再说通俗一点,就是自己起一个名字,这个 名字可以用来作为变量名,函数名,对象名等。在JavaScript中,虽然说标识符是自己取名字, 但是也是需要遵守一定的规则,其命名的规则大致可以分为2大类:硬性要求和软性要求
硬性要求
・1 .可以是由数字,字母,下划线和美元符号组成,不允许包含其他特殊符号
-2.不能以数字开头
• 3.禁止使用J avaScript中的关键词和保留字来进行命名
-4.严格区分大小写
软性要求
•望文知意
命名的3种方法
- 1. 匈牙利命名法
匈牙利命名法是微软公司下面以为匈牙利籍的程序员所发明的命名法则,其特点是标识符的名字 以一个或者多个小写字母开头,表示了该变量的数据类型。匈牙利命名法中特定字母所对应的含 义如下表:
数据类型 | 对应前缀 |
Array数组 | a |
Boolean 布尔 | b |
Float浮点 | f |
Function | fn |
Interger(int)整型 | i |
Object对象 | o |
Regular Expression 正贝 lj | re |
String字符串 | s |
前缀之后的是一个单词或多个单词的组合,该单词表明变量的用途。
例如:a_array, o_object, i_userAge, b_isPassed
- 2. 驼峰命名法
驼峰命名法实际上分为两种,一种是大驼峰,另外一种是小驼峰。
-大驼峰又被称之为帕斯卡命名法,就是每一个单词都是首字母大写
例如:UserName
-小驼峰和大驼峰的区别在于,小驼峰的第一个单词的首字母是小写,后面单词的首字母是大 写
例如:userName
- 3. 蛇形命名法
这种命名法常见于Linux内核,C++标准库,Boost以及Ruby, Rust等语言
蛇形命名法的特点在于单词与单词之间使用下划线进行分隔
例如:user_name, my_first_name
2-1-4关键字和保留字
首先需要弄清楚关键字和保留字的区别是什么。
ECMA-262描述了一组具有特定用途的关键字。这些关键字可用于表示控制语句的开始或结束, 或者用于执行特定操作等。按照规则,关键字是语言本身所保留的,不能用作标识符。
ECMA-262还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特 定的用途。但它们有可能在将来被用作关键字。
JavaScript中的关键字与保留字如下:
abstract、await、booleanx break、byte、case、catch、char、class、const、continue、 debugger、defaultx delete、do、 double、else、 enum、 export、extendsx false、final、 finally、float、for、functionx goto、if、implementsx import、in、instanceof、int、 interfacex let、long、native、new、null、packagex privatex protectedx public、return、 short、static、super、switch、synchronizedx this、throw、throws、transientx true、try、 typeof、var、volatile、void、while、with、yield
2-1-5数据类型介绍
在JavaScript中,数据类型整体上来讲可以分为两大类:简单数据类型和复杂数据类型
-简单数据类型
简单数据类型一共有6种:
string, symbol, number, boolean, undefined, null
其中symbol类型是在ES6里面新添加的基本数据类型
•复杂数据类型
复杂数据类型就只有1种
object
包括JavaScript中的数组,正则等,其类型都是object类型
查看数据类型
在JavaScript中,我们可以通过typeof运算符来查看一个数据的数据类型
2-2变量
接下来我们需要探讨一下对于任何编程语言来讲都是非常重要的一个东西,变量。所谓变量,就 是用于引用内存中存储的一个值。当然,我们在使用变量之前,还需要先做的一件事儿就是声明 变量。
2-2-1声明变量
在JavaScript中声明变量的方式有3种:var , let , const。其中var现在已经不推荐使用 了,因为会有变量提升等问题。(后面我们会具体来探讨此问题)
const和let的区别在于,const所声明的变量如果是简单数据类型,那么是不能够再改变 的。而let所声明的变量无论是简单数据类型还是复杂数据类型,在后面是可以改变的。示例如 下:
const声明变量
const name = 'Bill';
name = 'Lucy';
//TypeError: Assignment to constant variable.
let声明变量
let name = 'Bill';
name = 'Lucy';
console.log(name);
2-2-2变量的赋值与初始化
我们可以利用=来给一个变量进行赋值,给变量第一次赋值的过程,叫做变量的初始化。一般我 们在声明变量的时候就会将变量给初始化,如下:
let a = 3;
当然我们也可以一次性初始化多个变量,将其写在一行里面。
let x = 3,y = 4,z = 5;
如果声明变量时没有赋予初值,那么默认值为undefined
let a;
console.log(a);//undefined
2-2-3使用var声明变量
前面有提到过,在JavaScript中声明变量的方式有3种:var , let , const。其中var现在 已经不推荐使用了。这是因为使用var来声明变量会伴随着一些问题。当然,这些问题也经常被 看作是JavaScript的一些特点,例如重复声明和遗漏声明。
重复声明
如果是使用var关键字来声明的变量,那么是允许重复声明的。只不过这个时候会忽略此次声 明。如果重新声明并且带有赋值,则相当于是重新赋值
重复声明不带有赋值操作,JS引擎会自动忽略后面的变量声明
var test = 3;
var test;
console.log(test);//3
重新声明时如果带有赋值操作,那么会进行一个数据的覆盖
var test = 3;
var test = 5;
console.log(test);//5
需要注释重复声明仅仅是使用var关键字时可以这样,如果是在严格模式中,或者使用let或 者const的话是会报错的。
遗漏声明
如果试图读取一个没有声明的变量的值,JS会报错
console.log(a);
//ReferenceError: a is not defined
JS允许遗漏声明,即直接对变量赋值而无需事先声明,赋值操作会自动声明该变量
{
a = 5;
console.log(a);//5 }
console.log(a);//5
2-2-4作用域
所谓作用域,就是变量在程序中能够被访问到的区域。这里我们介绍一个全局作用域,一个局部 作用域
- 1. 全局作用域
这是js引擎一进来就处于的运行环境。在全局作用域的中所声明变量称之为全局变量。全局变量 的特点在于变量在任何地方都能被访问。
let a = 5;//这是一个全局变量
- 2. 局部作用域
在JavaScript中,一对大括号就可以产生一个局部作用域。局部作用域里面的变量称之为局部变 量,既然是局部变量,那么就只能在这个局部的作用域里面能访问到,外部是访问不到的。
{
let i = 10;
console.log(i);//10
}
console.log(i);
//ReferenceError: i is not defined
顺带一提的是,在大括号中用var声明的变量不是局部变量,而是一个全局变量。这其实也是最 早使用var来声明变量所遗留下来的一个问题。
{
var i = 10;
console.log(i);//10
}
console.log(i);//10
在局部作用域里面,如果变量名和全局作用域里面的变量名冲突,优先使用局部作用域里面的变
let i = 10;
{
let i = 100;
console.log(i);//100
}
console.log(i);//10
如果在局部作用域里面声明变量时没有书写关键字,那么会声明一个全局变量
{
i = 10;
}
console.log(i);//10
2-3数据类型
所谓数据类型,就是指数据不同的种类。
在JavaScript中,存在6种简单数据类型以及1种复杂数据类型。接下来,就让我们首先一起来看 —下JavaScript中6种简单的数据类型。
2-3-1 undefined 类型
undefined类型就只有一个值,undefined。在使用变量但是没有为其赋值的时候,这个变量的 值就是undefined o
还需要注意一点,就是没有申明的变量,使用时会报错,而不是undefined。但是打印其类型的 时候,显示的类型却是undefined
let i;
console.log(typeof i);//undefined
console.log(typeof j);//undefined
console.log(i);//undefined
console.log(j);
//ReferenceError: j is not defined
2-3-2 nulI类型
null类型的值也是只有一个,就是null。null表示一个空的对象。从逻辑角度来看,null值表 示一个空对象指针,这也正是用typeo f操作符检测null值时会返回o bject的原因。
示例:
let i = null;
console.log(typeof i);//object
实际上,undefined值是从null值派生而来的,因此当我们对这两个数据类型进行相等测试时,会
返回true
示例:
if(null == undefined){
console.log('Yes');//Yes
2-3-3布尔类型
所谓布尔类型,也被称之为boolean类型,就是真和假,这个类型的值只有两个,一个是true, 另一个是false
let i = true;
console.log(i);//true
console.log(typeof i);//boolean
需要注意的是,这两个值与数字值不是一回事,因此true不一定等于1,而false也不一定等于0。 还有一点就是Boolean类型的字面值true和false是区分大小写的。也就是说,True和False都不是 布尔值。
虽然Boolean类型的字面值只有2个,但是ECMAScript中所有类型的值都可以转换为Boolean类 型。可以使用Boolean()函数将其他类型转换为布尔值。
console.log(Boolean("Hello"));//true
console.log(Boolean(42));//true
console.log(Boolean(0));//false
最后需要注意的就是下面的9个值是对应布尔类型里面的假值
・““:双引号的空字符串
・”:单引号的空字符串
- '':空字符串模板
-0:数字0
- -0: JS中-0和0为不同的值
- NaN
- false
- null
- undefined
2-3-4数字类型
数字类型又被称之为number类型。number类型的值可以分为整数和实数两大类
1.整数
整数可以分为正整数和负整数,如下:
let a = 12;
let b = -7;
这个虽然没什么好说的,但是还是有一个注意点,那就是进制问题。二进制以Ob开头,八进制以 0开头,十六进制以Ox,示例如下:
//二进制
let a = 0b101;//5
//八进制
let b = 017;//15
//十进制
let c = 21;//21
//十六进制
let d = 0xFD;//253
console.log(a,b,c,d);
需要注意的是,不管参与运算的变量的值是什么进制,计算结果仍然会为十进制。
在ES6中提供了八进制数值新的写法,使用0。作为前缀,如下:
let a = 017;
let b = 0o17;
console.log(a,b);//15 15
- 2. 实数
所谓实数,就是我们平常所常见的小数,或者称之为浮点数。
在JavaScript里面,表示浮点数的方式有两种:小数型和科学记数法型 示例如下:
let a = 3.14;
let b = 9.12e+2;
console.log(a,b);//3.14 912
- 3. 数值范围(扩展)
由于内存限制,JavaScript并不能保存世界上所有的数值。在JS中能够表示的最小数值在绝大多 数浏览器中为5e-324,而最大值为1.7976931348623157e+308。通
过Number.MIN_VALUE和Number.MAX_VALUE我们可以查看到JS中支持的最小值和最大值。 示例:
console.log(Number.MIN_VALUE);//5e-324
console.log(Number.MAX_VALUE);//1.7976931348623157e+308
如果某次计算的结果超出了ECMAScript的数值范围,那么正数会被转化为infinity (正无穷), 负数会被转换为-infinity (负无穷)
例如:
根据ECMAScript的规定大于等于2的1024次方的数为无穷大
let i = Math.pow(2,1024);
console.log(i);//Infinity
根据ECMAScript的规定小于等于2的1024次方的数为无穷小
let i = -Math.pow(2,1024);
console.log(i);//-Infinity
如果某次计算返回了 infinity值,那么该值无法参与下一次计算,因为infinity不是能够参与计算的 数值。要想确定一个数值是不是有穷的,可以使用isFinite。函数。
示例:如果是无穷大数,会返回false,否则返回true(其实这个函数就是用于判断一个变量是否为 数值的)
let i = Math.pow(2,1024);
console.log(isFinite(i));//fasle
let j = 7;
console.log(isFinite(j));//true
- 4. NaN
英文全称为Not a Number,即非数值。这个数值用于表示本来要返回数值的操作数未返回数值的 情况(这样就不会抛出错误了)。
NaN有两个特点:任何涉及NaN的操作都会返回NaN
示例:
let a = NaN + 10;
console.log(a);//NaN
第二个特点是NaN和任何值都不相等,包括它自己本身,示例如下:
console.log(NaN === NaN);//false
除此之外,ECMAScript还定义了一个isNaN()函数,来帮助我们判断一个参数是否不是数值。 isNaNO函数在接收到一个值之后,会尝试将这个值转换为数值。
示例:
console.log(isNaN(NaN));//true
console.log(isNaN("123"));//false
console.log(isNaN(123));//false
console.log(isNaN("Hello"));//true
console.log(isNaN(true));//false
最后需要补充说明一下的是,NaN是属于number类型的,证明如下:
console.log(typeof NaN);//number
- 5. 数值转换
在JavaScript里面,有3个函数可以将非数值的数据转为数值,分别
是Number。,parseInt()以及parseFloat()这3个方法,下面我们将依次对这几个方法进
行介绍
Number():可以将非数值转为数值
使用Number()函数的时候,有下面几个规则需要注意:
•如果是Boolean值,true和false将分别被转换为1和0
-如果是数字,那么就是简单的传入和返回
•如果是null值,那么返回0
•如果是undefined,那么返回NaN
示例如下:
console.log(Number(true));//l
console.log(Number(false));//0
console.log(Number(10));//10
console.log(Number(null));//0
console.log(Number(undefined));//WaW
如果是字符串,那么又有如下的规则:
-如果字符串只包含数字,则将其转为十进制,即”1”会变成1, ”123”变成123,而”011”会变 为11 (注意这里不会被当成八进制来处理)
-如果字符串中包含有效的十六进制格式,如”1.1”,则将其转换为对应的浮点数值
•如果字符串中包含有效的十六进制格式,例如”0xf”,则会将其转换为相同大小的十进制整 数。
-如果字符串是空的,则将其转换为0
・如果字符串包含上述格式之外的字符,则将其转换为NaN
示例:
console.log(Number("1"
console.log(Number("012"));//12
console.log(Number("0o10"));//8 console.log(Number("0b111"));//7
console.log(Number("3.14"));//3.14 console.log(Number("0xf"));//15
console.log(Number(""));//0 console.log(Number("123Hello"));//NaN
parselnt。:也是将一个非数值转为数值
说明:相比number。函数,parselnt。会更多的看是否有数字,有就会将其转换为数值。最简单的 例子为number。函数转换”123Hello”时会转换为NaN,而parselnt。则会将其转换为123。
碰到空字符串时,number。函数会将其转换为0,而parselnt。则会将其转换为NaN 最后是在碰到小数时,会有一个取整的过程。例如”3.14”会被转换为”3” 示例:
console.log(parseInt("1"));//1
console.log(parseInt("012"));//12 console.log(Number("0o10"));//8
console.log(Number("0b111"));//7 console.log(parseInt("3.14"));//3
console.log(parseInt("0xf"));//15 console.log(parseInt(""));//NaN
console.log(parseInt("123Hello"));//123
我们的parseInt()从ES5开始还提供了第二个参数,那就是指定参数是多少进制,这 样parseInt()函数就可以将指定的进制转换为十进制,如下:
console.log(parseInt("012"));//12 console.log(parseInt("012",8));//10
//如果是16进制数,后面添加上参数16后,字符串前面可以不写0x
console.log(parseInt("AF"));//NaN
console.log(parseInt("AF",16));//175
除此之外,我们的parselnt()函数的第2个参数还可以是任意值,八进制前面不用加前面的0, 十六进制不用加前面的Ox
console.log(parseInt("21",3));//7
console.log(parseInt("10",2));//2
console.log(parseInt("11",8));//9 console.log(parseInt("AF",16));//175
parseFloatO:将非数值转为浮点数
说明:parseFloat()只解析十进制值,所以没有第二个参数,该函数会将带有小数点的字符串转换 为小数。如果没有小数点的数会被转换为整数。同样的parseFloatO也是尽可能转换更多的数值, 例如”123Hello”会被转换为123.
示例:
console.log(parseFloat("21"));//21 console.log(parseFloat("123Hello"));//123
console.log(parseFloat("0xA"));//0 console.log(parseFloat("3.14"));//3.14 console.log(parseFloat("22.34.5"));//22.34 console.log(parseFloat("0908.34"));//908.34 console.log(parseFloat("3.1415e2"));//314.15
ES6将全局方法parseInt()和parseFloatO等方法,移植到number对象上面,行为完全保 持不变,这么做的目的,是为了逐步减少全局性的方法,使得语言逐步模块化。
//ES5的写法
console.log(parseInt("12.34"));//12 console.log(parseFloat("12.34#"));//12.34
//ES6的写法
console.log(Number.parseInt("12.34"));//12 console.log(Number.parseFloat("12.34#"));//12.34
- 6. 静态方法(扩展)
这里是第一次听到静态方法这个说法。什么是静态方法呢?
所谓静态方法,主要是涉及到了面向对象里面的知识,这里简单理解,就是通过该类型能够直接
调用的方法。下面介绍两个Number类型的静态方法
Number.isIntegerO:用来判断一个值是否为整数。需要注意的是,在JS内部,整数和浮点数是同 样的存储方法,所以3和3.0被视为同一个值
console.log(Number.isInteger(25));//true console.log(Number.isInteger(25.0));//true console.log(Number.isInteger(25.1));//false console.log(Number.isInteger("15"));//false console.log(Number.isInteger(true));//false
Number.isFinite():这个方法我们前面在介绍数值范围的时候已经给大家介绍过了。如果一个值是 字符串,布尔类型,Infinity, -Infinity, NaN等(总之就不是数字的时候),则返回false,如果是数 字的话就会返回true。并且不会进行自动类型转换。
console.log(Number.isFinite(true));//false console.log(Number.isFinite(7));//true console.log(Number.isFinite(NaN));//false console.log(Number.isFinite(Infinity));//false console.log(Number.isFinite("23"));//false
- 7. 实例方法(扩展)
首先解释一下什么叫做实例方法。所谓实例方法,就是指必须要实例化对象,然后在对象上面调 用。这也涉及到了后面面向对象的知识。现在只需要知道要先有一个数,然后在这个数上面调用 相应的方法。
toFixed():toFixed()方法按照指定的小数位返回数值四舍五入后的字符串表示(常用于处理货币值)
|注意:toFixed。里的参数只接受0-20,若不传参或参数为undefined则相当于参数是0
let num = 10.456;
console.log(num.toFixed(2));//10,46 console.log(num.toFixed());//10 console.log(num.toFixed(0));//10 console.log(num.toFixed(undefined));//10
console.log(num.toFixed(-1));//扳错
//RangeError: toFixed() digits argument must be between 0 and 20
toExponential():返回数值四舍五入后的指数表示法(e表示法)的字符串表示,参数表示转换后的 小数位数
注意:toExponential。方法里的参数只接受0-20,但与toFxied。不同的是,若不传参或参数
为undefined,则保留尽可能多的有效数字;若参数是0表示没有小数部分
let num = 10.456;
console.log(num.toExponential(2));//1.05e+l console.log(num.toExponential());//1.0456e+l console.log(num.toExponential(0));//le+l console.log(num.toExponential(undefined));//1.0456e+1 console.log(num.toExponential(-1));//灰错
//RangeError: toExponential() argument must be between 0 and 20
toPrecision():接收一个参数,即表示数值的所有数字的位数(不包括指数部分),自动调用 toFixed ()或 toExponentialQ
注意:toPrecision()里的参数只接受1-21,若不传参或参数为undefined则相当于调用 toString()方法
let num = 10.456;
console.log(num.toPrecision(3));//10.5 console.log(num.toPrecision(2));//10 console.log(num.toPrecision(1));//1e+1 console.log(num.toPrecision());//10.456 console.log(num.toPrecision(undefined));//10.456 console.log(num.toPrecision(0));//灰错
//RangeError: toPrecision() argument must be between 1 and 21
注意:toFixed()、toExponential()、toPrecision()这三个方法在小数位用于四舍 五入时都不太可靠,跟浮点数不是精确储存有关
console.log((12.25).toPrecision(3));//12.3
console.log((12.25).toFixed(1));//12.3 console.log((12.25).toExponential(2));//1.23e+1 console.log((12.35).toPrecision(3));//12.3 console.log((12.35).toFixed(1));//12.3 console.log((12.35).toExponential(2));//1.23e+1
2-3-5字符串类型
- 1. 字符串介绍
这是程序里面使用最为广泛的一种类型。在JavaScript里面,可以使用单引号,也可以使用双引 号
let a = "abcd"; let b = 'abcd';
这里需要注意一个问题,就是字符串的内容本身包含单引号或者双引号的话,需要和字符串界限 符区分开,如下:
let a = "Hello 'World',welcome”;//正确
let b = 'Hello "World",welcome';//正确
let c = "Hello "World",welcome";//错误
当然,我们这里使用转义字符也是一个很好的选择,如下:
let a = "Hello 'World',welcome";//正确
let b = 'Hello "World",welcome';//正确
let c = "Hello \"World\",welcome";//正确
字符串这种数据类型非常的霸道,它和其他数据类型相加都会被转换为字符串类型,示例如下:
a = "abcd";
b = 13 + a;
c = 3.14 + a; d = true + a; e = null + a; f = undefined + a;
console.log(typeof console.log(typeof console.log(typeof console.log(typeof console.log(typeof
所以如果我们要让一个非字符串的变量转换为字符串的话,只需要和一个空字符串相加就可以 了。
当然,转换字符串事实上我们也有相应的函数来转换,最常见的就是toString()函数。
toStringO
说明:该函数会将除了 null和undefined以外的数据类型转换为字符串。
示例:
let a = 10,b = true,c = null,d;
console.log(typeof a.toString());//string
console.log(typeof b.toString());//string console.log(typeof c.toString());//灰错 console.log(typeof d.toString());
可以看到,程序报错,因为null和undefined并不能通过toString()函数来转换为相应的字符串。 还有一个知识点,就是toString()函数在转换数值的时候是可以带有参数的。可以将数值指定转换 为几进制
示例:
let i = 10;
console.log(i.toString());//10 console.log(i.toString(2));//1010
console.log(i.toString(8));//12 console.log(i.toString(10));//10
console.log(i.toString(16));//a
这个时候,JavaScript还有一个函数是String。,这个函数就可以5种数据类型都转换为字符串。 示例:
let a = 10,b = true,c = null,d; console.log(String(a),typeof console.log(String(b),typeof console.log(String(c),typeof console.log(String(d),typeof
- 2. 字符串模板
字符串模板
在ES6中新增了模板字面量是增强版的字符串,它用反引号(')标识
let str = 'Hello World';
console.log(str);//Hello World
console.log(typeof str);//string console.log(str.length);//11
以上代码中,使用模板字面量语法创建一个字符串,并赋值给message变量,这时变量的值与一
个普通的字符串无异
如果想在字符串中包含反引号,只需使用反斜杠'转义即可
ES6的模板字面量使多行字符串更易创建,因为它不需要特殊的语法,只需在想要的位置直接换 行即可,此处的换行会同步出现在结果中
let str = 'Hello
World';
console.log(str);
//Hello
//World
console.log(typeof str);//string
console.log(str.length);//12
在反引号之内的所有空白符都是字符串的一部分,因此需要特别留意缩进
模板字面量看上去仅仅是普通JS字符串的升级版,但二者之间真正的区别在于模板字面量的变量 占位符。变量占位符允许将任何有效的JS表达式嵌入到模板字面量中,并将其结果输出为字符串 的一部分
变量占位符由起始的$(与结束的}来界定,之间允许放入任意的JS表达式。最简单的变量占位 符允许将本地变量直接嵌入到结果字符串中
let name = "xiejie";
console.log('Hello,${name}');
//Hello,xiejie
占位符$(name}会访问本地变量name,并将其值插入到message字符串中。message变量会 立即保留该占位符的结果
既然占位符是JS表达式,那么可替换的就不仅仅是简单的变量名。可以轻易嵌入运算符、函数调 用等
let count = 10,price = 0.25;
console.log('${count} items cost $${(count*price).toFixed(2)}');
//10 items cost $2.50