一、JS概述
关于JavaScript的历史,语言特点,略。
二、JavaScript的组成
JavaScript是ECMAScript、文档对象模型(document object model:DOM)、浏览器对象模型(brower object model:BOM)由三部分构成,其核心是ECMAScript,它描述了该语言的语法和基本对象;DOM 描述了处理网页内容的方法和接口,通过 DOM,可以访问所有的 HTML 元素,连同它们所包含的文本和属性,可以对其中的内容进行修改和删除,同时也可以创建新的元素;BOM 描述了与浏览器进行交互的方法和接口,BOM提供了独立于内容而与浏览器窗口进行交互的对象,例如可以移动,调整浏览器大小的window对象,可以用于导航的location对象与history对象,可以获取浏览器,操作系统与用户屏幕信息的navigator与screen对象,可以使用document作为访问HTML文档的入口,管理框架的frames对象等。
三、JavaScript的引入方式
3.1外部引入
在<script></script>标签里面src=“ ”;中添加链接
<script type="text/javascript" src="yuanmi.js">
// 如果链接了外部JS文件,script标签里面的JS代码就不执行了
// 此处不能加JS代码
</script>
3.2内部引入
在script标签内添加
<script type="text/javascript">
<!-- script标签可以有多个,按顺序执行 -->
console.log("你好!")
</script>
四、基本概念
1、ECMAscript中的一切(变量、函数名,操作符)都区分大小写
2、标志符(标识符(identifier)指的是用来识别各种值的合法名称。最常见的标识符就是变量名,以及后面要提到的函数名):第一个字符必须是一个字母,下划线、美元符号。其他字符可以是字符、下划线。美元符号、或者是数字
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。
3、注释
- 单行注释://
- 多行注释:/* */
4、变量:ECMAscript的变量是松散型的,所谓松散型就是可以用来保存任何类型的数据、定义时要用var操作符,如果在函数中使用var定义一个变量,那么这个变量在函数退出 后就会被销毁,如果省略var,那么这个变量就成为全局变量,可以在函数外的任何一个地方被访问到,但是,不推荐这么使用。
- 变量是对值的具名引用,变量就是为“值”起名,然后引用这个名字,就等同于引用这个值
- 如果只是声明变量而没有赋值,则该变量的值是undefined
- 变量的类型没有限制,变量可以随时更改类型。
- 第二次声明的时候还进行了赋值,则会覆盖掉前面的值。
- 变量提升:JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升。表示变量已声明,但还未赋值
五、数据类型
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了第七种 Symbol 类型的值,本文不涉及。)
- 数值(number):整数和小数(比如1和3.14)
- 字符串(string):文本(比如Hello World)。
- 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
- undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
- null:表示空值,即此处的值为空。
- 对象(object):各种值组成的集合。
通常,数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值。
5.1 undefined
- 1、定义一个变量,但是没有初始化,会得到undefined
- 2、变量未定义,会得到undefined
- 3、函数中return不带任何返回值时,函数停止执行会返回undefined
- 4、函数参数arguments,没有传递值的命名参数将自动被赋予undefined
- 5、对象没有赋值的属性
var o = new Object(); o.p // undefined
5.2 Null
- null是只有一个值得数据类型,这个特殊值是null
- null值表示一个空对象指针,如果保存对象的变量还没有真正的保存对象,就应该明确的让该变量保存null值
特殊情况: - alert(null == undefined)//true
- alert(null === undefined)//false
5.3 Boolean
该类型有2个字面量值true和false,经常用在流程控制语句和选择判断语句,
常见false值,除了false值都基本都是true
- 1.数字0、
- 2.NaN、
- 3.“ ”,空字符串
- 4.false
- 5.undefined
- 6.null
下列运算符会返回布尔值:
- 前置逻辑运算符: ! (Not)
- 相等运算符:===,!==,==,!=
- 比较运算符:>,>=,<,<=
5.4 Number
1、浮点数:所谓浮点数,就是该数值中必须包含一个小数点,且小数点后面至少有一位数字,由于保存浮点数的内存空间是保存整数的2倍,因此,如果小数点后面没有任何数字,或者本身就是一个整数(1.0),那么该值会被转化成整数,但是浮点数计算会产生四舍五入误差的问题。
2、数值范围:由于内存的限制,ECMAScript 并不能保存世界上所有的数值。ECMAScript 能够表示的最小数值保 存在 Number.MIN_VALUE 中——在大多数浏览器中,这个值是 5e-324;能够表示的最大数值保存在 Number.MAX_VALUE 中——在大多数浏览器中,这个值是 1.7976931348623157e+308。如果某次计算的 结果得到了一个超出 JavaScript 数值范围的值,那么这个数值将被自动转换成特殊的 Infinity 值。具 体来说,如果这个数值是负数,则会被转换成-Infinity(负无穷),如果这个数值是正数,则会被转 换成 Infinity(正无穷)。
isFinite():这个函数在参数位于最小和最大值之间会返回true
3、NaN
这个数值表示一个本来要返回数值的操作数未返回的情况(这样不会抛出错误)
任何设计NAN的操作都会返回NaN,其次,NaN与任何值都不相等,包括NaN本身
isNaN():任何不能被转化成数值的值都会导致这个函数返回true
- 数值转化
Number():可以转化任何类型数据
parseInt():专门用于把字符串转化成整数
parseFloat():专门用于把字符串转化成浮点数
5.5 String
多个字符的有序序列,双引号和单引号引起来的都是字符串
转化成字符串
toString(),String()
两者区别:
1、除了null和undefined值,任何值都有toString()
2、toSring()接受一个参数,表示进制
3、String()能够将任何类型的值都转换成字符串toString()规则:值如果有toString,则调用该方法,如果值是null,则返回“null”,如果值是undefined,返回‘undefined’
六、检测数值类型
typeof()
typeof()是用来检测给定变量的数据类型,对一种值使用typeof操作符可能返回下列某个字符串
‘undefined’:这个值未定义
‘boolean’:这个值是布尔类型
‘string’:这个值是字符串
‘number’:这个值是数值
‘object’:这个值是对象或者null
‘function’:这个值是函数
typeof操作符用来区分函数和其他对象是有必要的
instanceof运算符
Object.prototype.toString方法
七、语句
7.1 条件语句
if语句
// if结构先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句
if (布尔值){
语句;
}
// 或者
if (布尔值) 语句;
if else语句
if (布尔值) {
// 满足条件时,执行的语句
} else {
// 不满足条件时,执行的语句
}
if ...else 语句
if (m === 0) {
// ...
} else if (m === 1) {
// ...
} else if (m === 2) {
// ...
} else {
// ...
}
switch语句
// 选择执行相应的case。如果所有case都不符合,则执行最后的default部分
// switch语句内部采用的是“严格相等运算符”
switch (x) {
case 1:
console.log('x 等于1');
break;
case 2:
console.log('x 等于2');
break;
default:
console.log('x 等于其他值');
}
三元运算符 ?:
// 如果“条件”为true,则返回“表达式1”的值,否则返回“表达式2”的值。
(条件) ? 表达式1 : 表达式2
't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"
7.2 循环语句
while循环
// While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。
while (条件) {
语句;
}
// 或者
while (条件) 语句;
for 循环
// 初始化表达式(initialize):确定循环变量的初始值,只在循环开始时执行一次。
// 条件表达式(test):每轮循环开始时,都要执行这个条件表达式,只有值为真,才继续进行循环。
// 递增表达式(increment):每轮循环的最后一个操作,通常用来递增循环变量。
for (初始化表达式; 条件; 递增表达式) {
语句
}
for语句的三个部分(initialize、test、increment),可以省略任何一个,也可以全部省略。
for ( ; ; ){
console.log('Hello World');
}
上面代码省略了for语句表达式的三个部分,结果就导致了一个无限循环。
do while语句:至少执行一次
// do...while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件。
// 不管条件是否为真,do...while循环至少运行一次,这是这种结构最大的特点。另外,while语句后面的分号注意不要省略。
do
语句
while (条件);
// 或者
do {
语句
} while (条件);
break 语句和 continue 语句
break语句用于跳出代码块或循环。
continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环
for (var i = 0; i < 5; i++) {
console.log(i);
if (i === 3)
break;
}
// 0
// 1
// 2
// 3
// 上面代码执行到i等于3,就会跳出循环
var i = 0;
while (i < 100){
i++;
if (i % 2 === 0) continue;
console.log('i 当前为:' + i);
}
// 上面代码只有在i为奇数时,才会输出i的值。如果i为偶数,则直接进入下一轮循环
标签(label)
JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置.
标签可以是任意的标识符,但不能是保留字,语句部分可以是任意语句。
标签通常与break语句和continue语句配合使用,跳出特定的循环。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// break命令后面加上了top标签(注意,top不用加引号),满足条件时,直接跳出双层循环。如果break语句后面不使用标签,则只能跳出内层循环,进入下一次的外层循环。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) continue top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2
// continue命令后面有一个标签名,满足条件时,会跳过当前循环,直接进入下一轮外层循环。如果continue语句后面不使用标签,则只能进入下一轮的内层循环。
八、操作符
++
: 自增
++
// 运算子首先转为数值,然后加上1或者减去1。它们会修改原始变量
// 自增和自减运算符是仅有的两个具有副作用的运算符,其他运算符都不会改变变量的值
var x = 1;
++x // 2
x // 2
--
: 自减
var x = 2;
--x // 1
x // 1
// 自增和自减运算符有一个需要注意的地方,
// 就是放在变量之后,会先返回变量操作前的值,再进行自增/自减操作;
// 放在变量之前,会先进行自增/自减操作,再返回变量操作后的值
var x = 1;
var y = 1;
// x是先返回当前值,然后自增,所以得到1
x++ // 1
++y // 2
// y是先自增,然后返回新的值,所以得到2
+
:加号操作符
// 1. 用来求两个数值的和
// 2. 两个字符串相加,这时加法运算符会变成连接运算符,返回一个新的字符串,将两个原字符串连接在一起
// 3. 一个运算子是字符串,另一个运算子是非字符串,这时非字符串会转成字符串,再连接在一起
'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"
// 4. 重载:加法运算符是在运行时决定,到底是执行相加,还是执行连接。也就是说,运算子的不同,导致了不同的语法行为,这种现象称为“重载”(overload)
// 5. 对象的相加
// 如果运算子是对象,必须先转成原始类型的值,然后再相加
// 对象转成原始类型的值,首先,自动调用对象的valueOf方法,一般来说,
// 对象的valueOf方法总是返回对象自身,这时再自动调用对象的toString方法,将其转为字符串,知道了这个就可以自己定义valueOf方法或toString方法,得到想要的结果
var obj = { p: 1 };
obj.valueOf().toString() // "[object Object]"
var obj = {
valueOf: function () {
return 1;
}
};
obj + 2 // 3
// 如果运算子是一个Date对象的实例,那么会优先执行toString方法
var obj = new Date();
obj.valueOf = function () { return 1 };
obj.toString = function () { return 'hello' };
obj + 2 // "hello2"
-
:主要用来表示负数
// 具有将一个值转为数值的功能,只不过得到的值正负相反
var x = 1;
-x // -1
-(-x) // 1
**
: 指数运算符
// 指数运算符(**)完成指数运算,前一个运算子是底数,后一个运算子是指数。
2 ** 4 // 16
// 指数运算符是右结合,而不是左结合。即多个指数运算符连用时,先进行最右边的计算
2 ** 3 ** 2
// 512
乘性操作符
乘法:*
除法: /
求模:%
// 余数运算符(%)返回前一个运算子被后一个运算子除,所得的余数
// 运算结果的正负号由第一个运算子的正负号决定。
// 为了得到负数的正确余数值,可以先使用绝对值函数
-1 % 2 // -1
1 % -2 // 1
// 错误的写法
function isOdd(n) {
return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false
// 正确的写法
function isOdd(n) {
return Math.abs(n % 2) === 1;
}
isOdd(-5) // true
isOdd(-4) // false
===
: 全等
// 如果两个值的类型不同,直接返回false
1 === "1" // false
// 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false
1 === 0x1 // true
//NaN与任何值都不相等(包括自身)。另外,正0等于负0
NaN === NaN // false
+0 === -0 // true
// 复合类型值: 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址
{} === {} // false
[] === [] // false
(function () {} === function () {}) // false
// 如果两个变量引用同一个对象,则它们相等。
var v1 = {};
var v2 = v1;
v1 === v2 // true
//对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。
//undefined和null与自身严格相等
undefined === undefined // true
null === null // true
var v1;
var v2;
v1 === v2 // true
!==
:不全等
// 先求严格相等运算符的结果,然后返回相反值
1 !== '1' // true
// 等同于
!(1 === '1')
==
:相等
// 1、原始类型的值会转换成数值再进行比较
'1' == true // true
// 等同于 Number('1') === Number(true)
// 等同于 1 ===
'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1
// 2、对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转换成原始类型的值,再进行比较。
// 对象与数值比较时,对象转为数值
[1] == 1 // true
// 等同于 Number([1]) == 1
// 对象与字符串比较时,对象转为字符串
[1] == '1' // true
// 等同于 String([1]) == '1'
[1, 2] == '1,2' // true
// 等同于 String([1, 2]) == '1,2'
// 对象与布尔值比较时,两边都转为数值
[1] == true // true
// 等同于 Number([1]) == Number(true)
[2] == true // false
// 等同于 Number([2]) == Number(true)
// 3、undefined和null与其他类型的值比较时,结果都为false,它们互相比较时结果为true
false == null // false
false == undefined // false
0 == null // false
0 == undefined // false
undefined == null // true
// 4、相等运算符的缺点
// 相等运算符隐藏的类型转换,会带来一些违反直觉的结果
0 == '' // true
0 == '0' // true
2 == true // false
2 == false // false
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
!=
: 不等运算符
// 它的算法就是先求相等运算符的结果,然后返回相反值
1 != '1' // false
// 等同于
!(1 == '1')
>
: 大于
//1、是否都是字符串,如果是的,就按照字典顺序比较(实际上是比较 Unicode 码点)
'cat' > 'catalog' // false
//2、如果不是字符串,就会将两个运算子都转成数值,再比较数值的大小
5 > '4' // true
// 等同于 5 > Number('4')
// 即 5 > 4
true > false // true
// 等同于 Number(true) > Number(false)
// 即 1 > 0
2 > true // true
// 等同于 2 > Number(true)
// 即 2 > 1
// 3、这里需要注意与NaN的比较。任何值(包括NaN本身)与NaN比较,返回的都是false。
1 > NaN // false
1 <= NaN // false
'1' > NaN // false
'1' <= NaN // false
NaN > NaN // false
NaN <= NaN // false
// 4、如果运算子是对象,会转为原始类型的值,再进行比较。
[2] > [1] // true
// 等同于 [2].valueOf().toString() > [1].valueOf().toString()
// 即 '2' > '1'
[2] > [11] // true
// 等同于 [2].valueOf().toString() > [11].valueOf().toString()
// 即 '2' > '11'
{ x: 2 } >= { x: 1 } // true
// 等同于 { x: 2 }.valueOf().toString() >= { x: 1 }.valueOf().toString()
// 即 '[object Object]' >= '[object Object]'
小于:<
大于等于:>=
小于等于:<=
=
: 赋值操作符
// 将 1 赋值给变量 x
var x = 1;
// 将变量 y 的值赋值给变量 x
var 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
布尔操作符
!
:逻辑非
// 取反运算符是一个感叹号,用于将布尔值变为相反值,即true变成false,false变成true
!true // false
!false // true
!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true
!54 // false
!'hello' // false
![] // false
!{} // false
&&
:且运算符
// 如果第一个运算子的布尔值为true,则返回第二个运算子的值(注意是值,不是布尔值);
// 如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值。
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""
var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1
// 且运算符可以多个连用,这时返回第一个布尔值为false的表达式的值。如果所有表达式的布尔值都为true,则返回最后一个表达式的值
true && 'foo' && '' && 4 && 'foo' && true
// ''
1 && 2 && 3
// 3
||
: 或运算符
// 如果第一个运算子的布尔值为true,则返回第一个运算子的值,且不再对第二个运算子求值;
// 如果第一个运算子的布尔值为false,则返回第二个运算子的值
't' || '' // "t"
't' || 'f' // "t"
// 或运算符可以多个连用,这时返回第一个布尔值为true的表达式的值。如果所有表达式都为false,则返回最后一个表达式的值
false || 0 || '' || 4 || 'foo' || true
// 4
false || 0 || ''
// ''
function saveText(text) {
text = text || '';
// ...
}
// 或者写成
saveText(this.text || '')
本文参考:JavaScript 教程