JavaScript基础

Javascript基础(高程三第一到五章)

一、JavaScript简介

1.简介:Javascript由ECMAScript(脚本语言标准)、文档对象模型DOM(Document Object Model)、浏览器对象模型BOM(Browser Object Model)三部分组成。

1.1.ECMAScript(脚本语言标准):类似于编程语言的变量怎么定义 操作符 保留字是什么的编程语言标准

1.2.文档对象模型DOM(Document Object Model):针对XML但经过拓展用于HTML的应用程序接口API。DOM将整个页面映射为一个多层结点结构。(操作页面结点)

1.3.浏览器对象模型BOM(Browser Object Model):处理浏览器窗口和框架,用于操作浏览器的功能(操作浏览器功能)

二、Javascript的使用

  1. 使用 script 标签在HTML页面插入Javascript代码,其中的代码由上到下解析
1
2
3
4
5
6
7
<script>标签的属性
可选属性:
//1.async (异步脚本):
//页面不用等待脚本的下载与执行,从而异步加载其他内容(只适用于外部js文件)
<script type="text/javascript" async src="example1.js"></script>
<script type="text/javascript" async src="example2.js"></script>
第二个脚本可能会在第一个脚本之前执行
1
2.charset:表示通过src属性指定代码的字符集
1
2
3.defer:立即下载js脚本但是延迟执行,等到页面完全解析再运行。
HTML页面中的嵌入js代码将忽视defer (只适用于外部js文件),但是会按照代码的顺序执行脚本,不同于async
1
2
3
4
5
6
7
8
4.src:引入外部js文件脚本
<script type="text/javascript" src="example.js"></script>

<script type="text/javascript" src="example.js">
function sayHi(){
alert("Hi");
} //中间这段代码不会被执行 只会执行外部引入的js脚本
</script>
1
2
3
必选属性:
1.type:表示编写代码使用的脚本语言内容类型
<script type="text/javascript"></script>
  1. 嵌入式的js代码写在页面内容的最后面, 标签的前面

三、Javascript基本概念

(一)变量

  1. 区分大小写

  2. 标识符:第一个字符必须是一个字母、下划线或美元符号

  3. 变量:使用var定义变量,定义出来的变量属于松散类型(可以用于保存任何数据类型,变量名只是用来当做一个保存数据值的占位符),使用var定义出来的变量是属于这个变量在其作用域中的局部变量

    1
    2
    var message; //message的值为undefined
    var message = "hi",number = 100,found = false;

(二)数据类型

  1. 由Undefined、Null、Boolean、Number和String + 复杂类型数据类型(Object)组成。(Object类型是由一组无序的名值对组成);Js不支持创建自定义类型数据(struct那些)。

  2. typeof操作符:用于检测给定变量的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>typeof操作符</title>
</head>
<body>

</body>
<script>
var message = "hi";
alert(typeof(message)); //string
</script>
</html>

3.五大数据类型+Object

3.1 Undefined类型:只有一个undefined值,使用var定义变量但是还没有初始化的时候该变量的值为undefined

1
2
3
4
5
6
7
8
9
<script>
// 数据类型1:Undefined
var message = undefined; //var message; typeof输出的结果是一样的
// var age;

console.log(typeof message); //undefined
console.log(typeof age); //undefined

</script>

上面的例子中可以看出 定义了值但是没有初始化的变量message和根本没有定义的变量age 使用typeof操作符判断的数据类型输出的都是undefined,输出结果一样但是技术层面上本质是完全不一样的

3.2 Null类型:只有一个值null,表示一个空对象指针,使用typeof操作符检测数据类型的时候会输出object

1
2
3
4
5
6
7
<script>
// 数据类型2:Null
var car = null;

console.log(typeof car); //object
console.log(car == undefined);//true
</script>

当定义的变量要保存的数据类型为对象的时候将变量初始化为null值,以区分该变量存储其他数据类型时的默认值undefined;undefined值是派生自null值的(所以使用==比较得到的是true)。

3.3 Boolean类型

1
2
3
4
5
6
7
8
9
10
<script>
// 数据类型3.Boolean
var found = true;
var notfound = false;

var message = "hi";
var booleanMessage = Boolean(message);
console.log(booleanMessage); //true

</script>

Js的数据类型都可以由Boolean()函数转化为对应的Boolean值,对应的转化如下

数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 空字符串
Number 任何非零数字值(包括无穷大) 0和null
Object 任何对象 null
Undefined Undefined

3.4 Number类型

3.4.1 进制转换

(1)Js的字面量格式的数值是十进制的;

(2)八进制(第一位必须是0,后面的数字序列要是07之间的数值,若字面值超过了07 那么八进制前面的0将会被忽略进而变成十进制的字面值)表示整数;

(3)十六进制(前两位必须是0x,后面的跟任何十六进制的数值09以及AF 字母可以大写也可以小写)表示整数

1
2
3
4
5
6
7
8
9
10
11
<script>
//数据类型4.Number类型
var intNum = 10; //十进制
var octalNum = 070; //八进制
var hexnum = 0x1f; //十六进制

console.log(intNum); //10
console.log(octalNum); //56
console.log(hexnum); //31
console.log("=======================");
</script>

3.4.2 浮点数值:数值中要包含小数点,且小数点后面至少要有一位数字。(浮点数值所需要的内存空间是保存整型数值的两倍)

1
2
3
4
5
6
7
<script>
var floatNum1 = 10.0;
var floatNum2 = 3.14e3; //科学计数法

console.log(floatNum1); //10
console.log(floatNum2); //3140
</script>

浮点数的最高精度是17位小数,算术运算的时候精确度远不足整数的精确度,所以0.1+0.2得不到0.3 ,而是0.30000000000000004 (小数点后面有17位小数)

3.4.3 数值范围:Number.MIN_VALUE 到 Number.MAX_VALUE

3.4.4 NaN(Not a Number):非数值是一个特殊的数值,任何涉及NaN的操作结果都是NaN,NaN不与任何值相等(即使是自己);isNaN()用于判断一个参数是否”不是数值”

1
2
3
isNaN(NaN); //true
isNaN(10); //false
参数不是数值范围true,是数值的话返回false

3.4.5 数值转换:非数值转换为数值

Number():可用于任何数据类型

image-20220109162708750

parseInt()与parseFloat():用于字符串数值转换为数值类型;

1
2
3
4
5
parseInt("10",2);//2 按二进制解析
parseInt("10",16); //16 按十六进制解析

parseFloat("1234blue"); //1234
parseFloat("123.12.65"); //123.12

3.5 String类型:”” 和 ‘’引起来的字符序列

1
2
3
4
5
6
7
8
9
// 数据类型5.String类型
var text = "Today is a good day!";
var Num = 10;
console.log(text.length); //20 输出字符串的字符个数
var strNum = Num.toString(); //将数值转换为字符串数值
console.log(strNum);
console.log(typeof strNum); //string
var found = true;
console.log(found.toString()); //输出字符串true; found.toString()不是布尔类型

null 和 undefined 没有toString()函数;

3.6 Object类型:一组数据和功能结合起来的数据类型

(三)语句

  1. for…in语句: 用于遍历对象属性。(遍历数组、对象属性(枚举对象属性))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 遍历数组元素   
<script>
// forin
///用for...in遍历"数组": 循环变量x是数组的下标 //
var arr=[22,33,44,55,66];
for(x in arr){
//Java中的x是数组元素,而js中的x是数组下标
//document.write(x+"&nbsp;"); //下标 : 0 1 2 3 4
console.log(arr[x]+"&"); //元素
}
</script>
输出:
22&
33&
44&
55&
66&
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
///用for...in遍历"js对象": 循环变量x是json的成员---属性 与 方法名; 然后对对象中的属性值进行操作
function Person(name, age){
this.name = name;
this.age = age;
this.toString = function(){
return this.name + "," + this.age;
}
}

var p = new Person("Jack",22);
for(x in p){
//document.write(x+"&nbsp;"); //属性与方法名: name age toString
//document.write(p.x+"&nbsp;");
console.log(p[x]+"&nbsp;"); //属性值与方法体
}
</script>

输出:
Jack&nbsp;
22&nbsp;
function(){
return this.name + "," + this.age;
}&nbsp;
  1. switch-case
1
2
3
4
5
6
7
8
9
10
11
12
switch (i){
case 25:
alert ("25");break;
case 35:
alert ("35");break;
case 45:
alert ("45");break;
default :
alert ("other") ;
}
Js switch特点:
switch中的值可以是任何值,case值不一定是常量 可以是变量、表达式

(四)函数

  1. 函数定义、参数、返回类型,函数是Function类型的一个实例,是一个对象(JS特色)
1
2
3
4
5
6
7
8
9
10
11
12
13
function sum(num1,num2){
return sum1 + sum2;
}

function sum(num1,num2){
return; //返回undefined 一般用于提前结束函数
}

function sum(number1,number2){
return number1 + number2;
}
var res = sum(10,10); //函数调用
console.log(res);
  1. arguments函数参数数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function sum(){
if(arguments.length==2){
return arguments[0] + arguments[1];
}
else{
return arguments[0] + arguments[1] + 1;
}
}
var res2 = sum(10,10);
var res3 = sum(10,10,2099);
console.log(res2);
console.log(res3);
//使用函数的arguments属性数组模拟多态

==============================================================================

//定义了俩参数 但是只传一个参数的话arguments数组的第二个元素arguments[1]的值为undefined
function sum2(number1,number2){
if(arguments.length == 1){
console.log(arguments[0] + 100);
console.log(arguments[1]); //undefined
}
else{
console.log("传入函数的参数个数为:" + arguments.length);
}
}

sum2(10); //110 undefined
sum2(10,10,2099); //传入函数的参数个数为:3


  1. Js函数无重载(重载:函数名相同但是用不同的函数参数或者参数个数加以区分) 但是可以使用arguments数组进行模仿多态(判断传入参数的个数来进行对应的函数数据处理)

  2. 函数声明与函数表达式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 函数声明 : 直接声明一个函数
    function foo() {
    console.log("Hello");
    }

    //函数表达式:将函数写好之后赋值给一个用var声明的变量
    // 匿名函数表达式(function后面没有函数名)
    var foo = function() {
    console.log('anonymous function expression');
    };

    // 具名函数表达式(function后面有函数名)
    var foo = function bar() {
    console.log('named function expression');
    };

四、Javascript变量、作用域和内存问题

(一)基本类型和引用类型的值

  1. JS的变量时松散类型的,这个本质决定了JS的变量只是在一段时间内用于保存某个特定值而已,不想其他的语言声明定义那样要向下面Java那样定义变量。JS定义的number可以是string类型的字符串 也可以是布尔类型的true,而variety就不能像JS这样定义的变量那样,只能是保存int类型数据
1
2
int variety = 10; //Java定义变量
var number = 10; //JS定义变量
  1. JS变量会有两种值:基本类型和引用类型;

    基本类型指的是简单的数据段:Undefined、Null、Boolean、Number、String都属于基本类型

    引用类型指的是可能由多个值所构成的对象.引用类型的值是保存在内存中的对象,但是JS没有直接访问内存中对象的机制,操作对象实际上是操作对象的引用

  1. JS引用类型变量的动态属性:定义基本类型值和引用类型值的方式是类似的:创建变量+赋值,但是引用类型和基本类型保存到内存之后对变量的操作有很大的差别如下,但是基本类型所创建的变量没有这种属性,这是两种类型的差异一。

    引用类型:

    1
    2
    3
    4
    5
    <script>
    var person = new Object(); //创建对象(引用类型)
    person.name = "Morant";
    console.log(person.name); //最基础的就是定义引用类型对象的属性,然后访问
    </script>
  2. 复制变量值:基本类型值的赋值,操作完成之后变量之间的值都是一样的,但是变量之间是互不影响的,改变其中一个变量的值拷贝的值变量值不会发生改变。

    1
    2
    3
    4
    5
    6
    7
    8
    var num1 = 10;
    var num2 = num1;
    console.log(num1); //10
    console.log(num2); //10

    num2 = 100;
    console.log(num1); //10
    console.log(num2); //100

    image-20220111170109277

但是引用类型变量的复制会不同于上述的基本类型值的复制,当一个变量向另一个变量复制引用类型的值时,会将复制过来的值存放到新的内存中,但是,存放到新的内存中的副本值是一个指针,指向的是存储在堆中的一个对象,完成复制后实际上是在两个不同内存空间上的两个变量指向的同一个存储在堆中的一个对象,这时改变一个引用类型变量的某个属性之后,拷贝的副本对应的属性也会发生改变。

1
2
3
4
5
6
7
8
9
10
var obj1 = new Object();
var obj2 = new Object();

obj1.name = "Morant";
obj2 = obj1;
console.log(obj2.name); //Morant

obj2.name = "Boom";
console.log(obj2.name); //Boom
console.log(obj1.name); // Boom

image-20220111170040924

  1. 传递参数(有意思的一点):JS中所有的函数参数都是按值传递的!

    当函数传递的参数是基本类型的话,和其他的开发语言是一样的,传进去改造加工,外面用一个值接收加工后的值,但是原料(number)是没有变的,函数中num只是原料(number)中的一个副本,这说明了函数的参数传递是按值传递。

    1
    2
    3
    4
    5
    6
    7
    var number = 10;
    function sum(num){
    return num + 10;
    }
    var result = sum(number);
    console.log(number); //10
    console.log(result); //20

    当函数传递的参数是引用类型的话,这里就需要区分一下一个易混点,如下代码:

    1
    2
    3
    4
    5
    6
    var person = new Object();
    function setName(obj){
    obj.name = "Morant";
    }
    setName(person);
    console.log(person.name);//Morant

    这个例子表面上看上去是在函数这个局部作用域中为函数外的外部作用域中定义的person添加了name属性,然后外部作用域可以得到person的name就是Morant,这很明显符合按引用传递参数,(易混点:局部作用域中操作外部作用域中对象的引用为其加上name属性,就是按引用传递的函数参数,不然外部的变量怎么会被内部作用域的操作改变了外部作用域中对象的值呢?就像基本类型那样,经过了函数,出来之后发现原料自己变了,但实际上并不是这样的)

    推翻上面的例子代码如下,真正说明函数的参数全部都是按值传递的,没有按引用传递:

    1
    2
    3
    4
    5
    6
    7
    8
    var person = new Object();
    function setName(obj){
    obj.name = "Morant";
    obj = new Object(); //新的引用
    obj.name = "Boom";
    }
    setName(person);
    console.log(person.name);//Morant

    上面的例子函数中再重新为传入函数的参数person设置完name属性之后,重新创建了一个对象赋值给参数person,然后这只person的name属性为Boom,但是外部输出person的name发现还是Morant。(如果有按引用传递参数的话,传进函数的person应该会存储堆中另一个对象B的引用值,并且这个对象B的name属性是Boom,这时按照引用传递参数的机制解释的话,外部的person指向的是在函数中新创建的对象B的引用,外部输出的name值应该是Boom,但并不是这样的) 这说明了JS的函数参数传递都是按值传递的,没有按引用传递。

  1. 检测类型

    检测基本类型使用typeof,检测引用类型使用instanceof;(使用typeof检测引用类型(null、对象)的话返回的都是Object)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var number = 10;
    var person = new Object();
    var arr = new Array(3);
    var res1 = person instanceof Object;
    var res2 = arr instanceof Array;
    var res3 = number instanceof Object;

    console.log(res1);// true
    console.log(res2);// true
    console.log(res3);// false
    //是引用类型的话返回的是true,否则返回false

(二)作用域(执行环境)与作用域链

执行环境官方解答(高程三第四章小结):所有变量(包括基本类型和引用类型)都存在于一个执行环境(也成为作用域)中(以下称之为作用域),这个作用域决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出—–例如关闭网页或浏览器——时才会被销毁)

  1. 作用域:分为全局作用域 和 函数(私有)作用域;每个作用域都与一个变量对象相关联,这个作用域里面的东西归这个作用域里面的变量对象管控(就像一个对象里面有属性和方法那样,定义对象你可以定义属性和方法,对象里面类似一个作用域),那么从大局来看,直接写代码定义一个变量,那么这个变量也看成是属于一个“对象”,不过这个对象不是我们用的,是后台的解析器处理数据的时候使用的。

    (1)全局作用域:最外围的一个作用域,Web浏览器中全局作用域被认为是window对象,所有的全局变量和函数都理解为是这个对象的属性与方法。

    (2)函数作用域:函数执行都会形成一个局部作用域,函数形成的函数作用域的话函数的活动对象被看成是这个函数作用域的变量对象,活动对象刚开始会包含一个arguments变量(函数那章提到的函数参数存放的地方),全局作用域没有arguments

  2. 作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链(作用域形成的链条)。这个作用域链始终是从当前代码所属的作用域出发,往外部延伸,最终到全局作用域中。这样的机制决定了为什么函数内部可以使用函数外部的变量,但是函数外部不能访问或使用函数内部的变量的原因(作用域链由前到后,由内及外(但仍是从上到下解析))。变量的查找是沿着作用域链来实现的,所以也称作用域链为变量查找的机制。这个机制也说明了访问局部变量要比访问全局变量更快,但是这个快的程度可以忽略不计。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <script>
    var number = 10;
    function sum(){
    var Num1 = 100;
    return Num1 + number;
    }
    var res = sum();
    console.log(res); //110
    </script>

    image-20220111235939808

​ 作用域链前后首尾:

image-20220111211559198

  1. 标识符的解析过程就是沿着作用域链一级一级(由内及外)往外搜索的过程,直到找到标识符为止,最终会到全局作用域,如果这时还没有找到标识符(定义的变量名)的话,将会报错;如果有多个相同的标识符,以由内及外最先搜索到的为准。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var number = 10;
    function sum(){
    var number = 20;
    function sum2(){
    return number + 10;
    //往外找 首先找到sum函数里面有一个number 20 就用它了 找不到全局作用域中的number 10
    }
    return sum2();
    }
    var result = sum();
    console.log(result);//30
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    tips:测试代码对函数的返回值不熟悉的地方,与主题内容作用域无关,一个注意事项

    =================================

    注意要返回函数的结果是要调用函数之后再返回函数return回来的结果
    var res = function sum(){
    return 1+1;
    }
    console.log(res) //控制台输出的是函数代码本身

    要返回2要是这样
    function sum(){
    return 1+1;
    }
    var res = sum();
    console.log(res);//2
  2. 没有块级作用域:Js不会因为{ }的存在而产生在{ }内的块级作用域,其他的类C语言会有这样的机制,这是js与其他语言的区别:

    1
    2
    3
    4
    5
    for(var i=0;i<2;i++){
    var number = 10;
    console.log(number);
    }
    console.log(number); //10

    在其他的类C语言中 这样的代码会报错,因为{ }中的代码在执行完之后,块级作用域的变量所占用的内存将会被释放,外部无法访问。但是Js可以访问。块级作用域详细见Javascript有关块级作用域的问题

(三)垃圾收集

  1. 垃圾回收机制:找出那些不再继续使用的变量释放其占用的内存。

  2. 就函数中的局部变量来说,当函数执行结束之后,函数中的变量就没用了,这个时候函数中的变量占据的内存就要被释放掉,但不是所有的变量情况都是这么简单判断的。垃圾收集器要跟踪哪些变量有用哪些变量没用来检测标识符,通常有两种策略。

    (1)标记清除(mark-and-sweep)

    ​ JS最常用的垃圾收集方式,当变量”进入环境”(在函数中定义一个变量的时候),将这个变量标记为进入环境,因为执行流进入函数的时候会用到那些进入环境的变量,所以不能释放这些将要用到的变量。当变量离开环境的时候(举例我理解为当函数执行结束的时候),将其标记为”离开环境”。垃圾收集器会将内存中的所有变量加上标记(这一步可能是用来统计程序运行时内存中有多少个变量了),然后再去掉标记,在这之后被加上标记的变量将被视为要删除的变量,最后垃圾收集器释放掉离开环境的变量所占的内存并回收。

    (2)引用计数(reference counting)及其他可以垃圾回收可以康康下面的帖子,这部分内容暂时有点深奥,感觉目前由于概念问题扎进去感觉也不是能马上明白:https://www.jianshu.com/p/a8a04fd00c3c

五、Javascript引用类型

  1. 引用类型:引用类型的值(对象)是引用类型的实例,在ES中引用类型是一种数据结构。

    1
    var person = new Object();

(一)Object类型

  1. 创建Object实例的两种方式:构造函数法和字面量法(不会调用Object构造函数)

    1
    2
    3
    4
    //构造函数法
    var person = new Object();
    person.name = "Morant";
    person.age = 20;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //字面量法,属性之间使用逗号隔开,
    var person = {
    name:"Morant",
    age:20,
    sayHello:function(){
    console.log("My name is "+ this.name);
    }
    }
    console.log(person.name);
    console.log(person.age);
    person.sayHello();
  2. 访问属性的方式:点表示法和[ ]表示法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var person = {
    name:"Morant",
    age:20,
    sayHello:function(){
    console.log("My name is "+ this.name);
    }
    }
    console.log(person.name); //使用对象类型的方式访问属性
    console.log(person["name"]);//使用person 变量 的方式来访问属性

(二)Array类型

  1. JS中的数组与其他语言数组的区别:

    (1)ES的数组每一项可以保存不同的数据类型(第一个保存字符串、第二个保存对象…)

    (2)ES的数组大小可以动态调整

  2. 创建数组的两种方式:构造函数法和字面量法

    1
    2
    var arr = new Array(10);//构造函数法
    var arr = ["Morant","Thomas","Boom"]; //字面量法
  3. JS的数组长度不是只读的,可以通过设置数组的长度达到调整数组的目的

    1
    2
    3
    4
    5
    6
    7
    var arr = new Array("Morant","Thomas","Boom");
    console.log(arr.length); //3
    arr.length = 2;
    console.log(arr[2]);//undefined

    arr[arr.length] = "Boom";
    console.log(arr[2]); //Boom
  4. 输出数组的几种方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var arr = new Array("Morant","Thomas","Boom");
    for(let i=0;i<arr.length;i++){
    console.log(arr[i]);
    }

    for (const i in arr) {
    console.log(arr[i]);
    }

    arr.forEach(element => {
    console.log(element);
    });
  5. 检测数组:检测某个变量是否是Array类型,使用Array.isArray(Value)方法判断

    1
    2
    var arr = new Array("Morant","Thomas","Boom");
    console.log(Array.isArray(arr)); //true

    也可以使用instanceof来检测,但是得到的结果是Object,原因是Array是起源自Object类型,但是具体的方式还是使用ES5新增的这个Array.isArray()较好

  6. 输出数组数据的字符串表示方式

    1
    2
    3
    4
    5
    var arr = new Array("Morant","Thomas","Boom");
    console.log("输出数组数据的字符串形式")
    console.log(arr.toString()); //Morant,Thomas,Boom
    console.log(arr.valueOf()); //(3) ['Morant', 'Thomas', 'Boom']
    console.log(arr.toLocaleString()); //Morant,Thomas,Boom

    image-20220113144602580

  7. 数据结构API:JS提供了模拟数据结构的方法

    (1)模拟栈

    1
    2
    3
    4
    5
    var arr = new Array("Morant","Thomas","Boom");
    arr.push("Gorege");
    console.log(arr.valueOf()); //['Morant', 'Thomas', 'Boom', 'Gorege'] 从数组尾部push压入元素
    arr.pop();
    console.log(arr.valueOf()); //['Morant', 'Thomas', 'Boom'] 从数组尾部pop弹出元素

    (2)模拟队列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //正向模拟,队头出队,队尾入队
    var arr = new Array("Morant","Thomas","Boom");
    arr.push("Gorege");
    console.log(arr.valueOf()); //['Morant', 'Thomas', 'Boom', 'Gorege'] 从数组尾部push压入元素
    arr.shift();
    console.log(arr.valueOf()); //['Thomas', 'Boom', 'Gorege'] 将数组元素从数组首部弹出

    //反向模拟,队头入队,队尾出队
    var arr = new Array("Morant","Thomas","Boom");
    arr.unshift("Gorege");
    console.log(arr.valueOf()); //['Gorege', 'Morant', 'Thomas', 'Boom'] 从数组首部压入元素
    arr.pop();
    console.log(arr.valueOf()); //['Gorege', 'Morant', 'Thomas'] 将数组元素从数组尾部弹出

    (3)重排序

    1
    2
    3
    4
    5
    6
    7
    var arr = [1,2,3,4,5];
    console.log(arr.reverse()); //[5, 4, 3, 2, 1]
    console.log(arr.reverse().sort()); //[1, 2, 3, 4, 5]

    //sort()会调用数组每一项的toString()方法,然后比较字符串确定排序,会有Bug
    var arr = [1,-1,10,15,5];
    console.log(arr.sort()); //[-1, 1, 10, 15, 5]

    适合大多数数据类型的排序方法

    1
    2
    3
    4
    5
    6
    7
    var arr = [1,-1,10,15,5];

    function compare(value1,value2){
    return value1 - value2; //升序
    //return value2 - value1; //降序
    }
    console.log(arr.sort(compare)); //[-1, 1, 5, 10, 15]
  8. 操作数组API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    concat():连接创建新的数组

    var arr = ["Morant","Thomas","Boom"];
    var arr2 = arr.concat("Gorege",["Lebron","Irvine"]);
    console.log(arr2); //['Morant', 'Thomas', 'Boom', 'Gorege', 'Lebron', 'Irvine']
    ===========================

    slice():基于当前数组创建几个数组
    一个参数代表从数组下标当前位置到数组尾
    两个参数代表返回从这两个数组下标参数之间的元素,但是不包括最后一个元素,头还是包括的

    var arr = ["Morant","Thomas","Boom"];
    var arr2 = arr.concat("Gorege",["Lebron","Irvine"]);
    console.log(arr2); //['Morant', 'Thomas', 'Boom', 'Gorege', 'Lebron', 'Irvine']

    console.log(arr2.slice(0)); // ['Morant', 'Thomas', 'Boom', 'Gorege', 'Lebron', 'Irvine']
    console.log(arr2.slice(1)); //['Thomas', 'Boom', 'Gorege', 'Lebron', 'Irvine']
    console.log(arr2.slice(1,3)); //['Thomas', 'Boom'] 下标1和下标2位置的元素
    ===========================

    splice():主要用途是向数组中部插入项
    1.删除任意数量的数据项,第一个参数是从哪开始,第二个参数是往后几项
    2.指定位置插入任意数量的项,起始位置,0(删除项数),插入的元素
    3.指定位置插入任意项,同时删除任意项
  9. 根据元素查找该元素在数组中的下标(用数据找下标),没找到返回-1

    1
    2
    3
    4
    var arr = ["Morant","Thomas","Boom"];
    console.log(arr.indexOf("Morant")); //0
    console.log(arr.lastIndexOf(2)); //-1
    console.log(arr.lastIndexOf("Morant")); //0 从数组尾部开始找起,但是数组的下标还是重头开始0、1、2...
  10. 迭代方法和缩小方法

1
2
3
4
5
6
7
8
9
10
迭代方法:
every()
filter()
forEach()
map()
some()

缩小方法:
reduce()
reduceRight()

(三)Date类型

  1. 使用Date类型的构造方法创建Date对象,可以获取当前的时间

    1
    2
    var date = new Date();
    console.log(date); //Tue Jan 18 2022 16:48:39 GMT+0800 (中国标准时间)
  1. 创建指定时间的日起对象

    1
    2
    var date = new Date("May 25,2004");
    console.log(date);//Tue May 25 2004 00:00:00 GMT+0800 (中国标准时间)
  1. Date类型常用API(用于获取日期)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var date = new Date();
    console.log(date.toTimeString()); //16:58:51 GMT+0800 (中国标准时间)
    console.log(date.toDateString()); //Tue Jan 18 2022
    console.log(date.toUTCString()); //Tue, 18 Jan 2022 09:00:01 GMT

    console.log(date.getFullYear()); //2022
    console.log(date.getMonth()); //0 (0表示1月,11表示12月)
    console.log(date.getDate()); //18
    console.log(date.getDay()); //2 (星期二)
    console.log(date.getHours()); //17 (时)
    console.log(date.getMinutes()); //3 (分)
    console.log(date.getSeconds()); //7 (秒)

(四)RegExp类型

  1. 用于支持正则表达式

(五)Function类型

  1. 在JS中函数是一个对象,函数名是指向函数对象的一个指针

  2. 函数的声明式语法与函数表达式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    声明式语法:
    function sum(num1,num2){
    return num1 + num2;
    }

    函数表达式:
    var sum = function(num1,num2){
    return num1 + num2;
    }
  3. 函数名仅是指向函数对象的一个指针

    1
    2
    3
    4
    5
    6
    7
    var sum = function(num1,num2){
    return num1 + num2;
    }
    console.log(sum(1,2)); //3
    var anotherSum = sum;
    sum = null;
    console.log(anotherSum(1,2)); //3
  1. JS函数无重载:从函数名代表着一个指针就可以更好地理解为什么JS函数没有重载,每个函数的函数名对应着各自的指针(做不到类Java语言那种函数名相同但是可以通过函数参数来区分每个函数用来干什么),但是可以通过函数中的arguments对传入函数的参数进行判断进而作出不同的功能(模拟重载)。

  2. 函数声明与函数表达式的区别!

    这涉及到函数提升与函数表达式提升的问题,JS的提升顺序从高到低:函数提升 > 函数表达式 > 变量

    (1)函数声明提升(function declareation hoisting):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    console.log(sum(1,2)); //3
    function sum(num1,num2){
    return num1 + num2;
    }

    实际的代码逻辑:(将函数声明整体提升)
    function sum(num1,num2){
    return num1 + num2;
    }
    console.log(sum(1,2)); //3

    (2)函数表达式提升

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    console.log(sum(1,2)); //Uncaught TypeError: sum is not a function
    var sum = function(num1,num2){
    return num1 + num2;
    }

    实际的代码逻辑
    var sum; //undefined
    console.log(sum(1,2)); //Uncaught TypeError: sum is not a function
    sum = function(num1,num2){
    return num1 + num2;
    }

    体现出函数表达式提升的例子
    console.log(sum); //undefined
    console.log(sum(1,2)); //Uncaught TypeError: sum is not a function
    var sum = function(num1,num2){
    return num1 + num2;
    }
  1. 作为值的函数(函数看成一个值来进行操作)

    1
    2
    3
    4
    5
    6
    7
    8
    // 返回其他函数执行结果的函数
    function returnOther(someFunction,args){
    return someFunction(args);
    }
    function sum(num1){
    return num1 + 100;
    }
    console.log(returnOther(sum,100));//200
  1. 函数的属性与方法

    (1)内部属性arguments与this

    arguments对象:类数组对象,包含着传入函数的参数

    this对象:代表当前的引用类型具体是哪个,处于”这个”引用类型的执行环境(作用域)下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    window.color = "red";
    var o = {
    color : "blue"
    }
    function sayColor(){
    console.log(this.color);//输出当前执行环境的color值(当前属于哪个引用类型的执行环境(作用域))
    }
    sayColor();//red
    o.sayColor = sayColor; //引用值给到它
    o.sayColor();//blue

    (2)length属性与prototype属性

    length:指明当前函数接收多少个参数

    1
    2
    3
    4
    function sayColor(){
    console.log(this.color);//输出当前执行环境的color值(当前属于哪个引用类型的执行环境(作用域))
    }
    console.log(sayColor.length); //0

    prototype:

    (3)apply()方法与call()方法:专出一篇仔细区分 :https://blog.csdn.net/weixin_42321292/article/details/82352997

(六)基本包装类型(少用)

  1. 将基本类型包装成引用类型进行操作,基本类型就有了像对象那样可以添加属性和方法,可分为Boolean类型、Number类型、String类型。(自己就是基本类型,但是有引用类型的属性与方法)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    String类型的包装:
    var s1 = new String("Hello");
    console.log(s1); //String {'Hello'}
    console.log(typeof s1); //object
    s1.name = "Aloha";
    console.log(s1.name); //Aloha

    Number类型的包装:
    var num = new Number(100);
    console.log(num); //Number {100}
    console.log(typeof num);//object
    console.log(num.toString()); //100

    Boolean类型的包装:
    var flag = new Boolean(false);
    console.log(typeof flag);//object
    console.log(flag);//Boolean {false}
    console.log(flag && true);//true (object && true);
    console.log(flag && false);//false (object && false);

(七)单体内置对象

  1. 程序执行之前就已经存在的对象,不用实例化就能用(例如Object、Array、String)。还有两个单体内置对象Global和Math

  2. Global对象:看上去不存在的对象,但是是JS里面兜底的对象,所有不属于其他对象的属性与方法都属于这个对象

    (1)Global的 eval() 方法:一个完整的JS解析器,它接收的参数就是JS代码

    1
    2
    var message = "Hello";
    eval("console.log(message)");//Hello (参数就是JS代码,字符串形式的)
    1
    2
    eval("function sayHello(){console.log('Hello');}"); //要写在一行里面
    sayHello(); //Hello
  3. Math对象:其对象与方法用于辅助完成数学运算


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!