JavaScript 网页编程(一)——JavaScript 基础语法

目录

一.计算机编程基础

二.初识 JavaScript

三.JavaScript 变量

四.JavaScript 数据类型

五.标识符、关键字、保留字

六.JavaScript 运算符(操作符)

七.JavaScript 流程控制

八.JavaScript 数组

九.JavaScript 函数

十.JavaScript 作用域

十一.JavaScript 预解析

十二.JavaScript 对象

十三.JavaScript 内置对象

十四.JavaScript 简单数据类型和复杂数据类型


一.计算机编程基础

1.计算机语言分类

  • 机器语言,汇编语言,高级语言。
  • ①机器语言:计算机最终所执行的都是 01机器语言。
  • ②汇编语言:和机器语言实质相同,直接对硬件操作,但更好记。

2.翻译器

  • 高级语言程序不能直接被计算机识别,必须经过转换,需要翻译器:将源代码转换为机器语言,也称二进制化。

3.编程语言和标记语言的区别

  • 编程语言是主动的,有很强的逻辑性。
  • 标记语言不向计算机发出指令,是被动的,用来被读取的。

4.数据存储

  • 硬盘、内存保存的是 二进制数据;安装软件本质:把程序文件复制到硬盘中。
  • 数据存储单位:
  1. 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
  2. 字节(Byte):1B = 8b
  3. 千字节(KB):1KB = 1024B
  4. 兆字节(MB):1MB = 1024KB
  5. 吉字节(GB): 1GB = 1024MB
  6. 太字节(TB): 1TB = 1024GB
  • 计算机运行软件的过程:
  1. 打开某个程序时,先从 硬盘 中把程序的代码加载到 内存 中。
  2. CPU执行 内存 中的代码(cpu运行快,只从硬盘读数据浪费cpu性能,用内存过渡(内存是电,硬盘是机械)

二.初识 JavaScript

1.JavaScript 定义

  • 运行在客户端的脚本语言 (Script 是脚本的意思)。
  • 不需要编译,运行过程中由 JS 解释器(JS引擎)【逐行】解释并执行,浏览器本身不执行 JS 代码。
  • 现在也可以基于 Node.js 技术进行服务器端编程。
  • 使用方式:行内式、内嵌式、外部JS。
<head>
    <!-- 2.内嵌式的js -->
    <script>
        // alert('沙漠骆驼');
    </script>
    <!-- 3. 外部js script 双标签 -->
    <script src="my.js"></script>
</head>

<body>
    <!-- 1. 行内式的js 直接写到元素的内部 -->
    <!-- <input type="button" value="唐伯虎" onclick="alert('秋香姐')"> -->
</body>
  • 浏览器分成两部分:渲染引擎 和 JS 引擎 
  1. 渲染引擎:用来解析HTML与CSS,俗称内核,比如 chrome 浏览器的 blink ,老版本的 webkit
  2. JS 引擎:也称为 JS 解释器。 用来读取网页中的JavaScript代码,对其处理后运行,比如 chrome 浏览器的 V8

2.JavaScript 作用

  • 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
  • 网页特效
  • 服务端开发(Node.js)
  • 桌面程序(Electron)
  • App(Cordova)
  • 控制硬件-物联网(Ruff)
  • 游戏开发(cocos2d-js)

3.JavaScript 组成

  • ECMAScript:规定 JS 的基础语法。
  • DOM(文档对象模型):提供接口,对页面上的各种元素进行操作(大小、位置等)。
  • BOM(浏览器对象模型):提供与浏览器窗口进行互动的对象结构,如弹出框、控制浏览器跳转、获取分辨率等。

4.JavaScript 输入输出语句

方法 说明 归属
alert(msg) 浏览器弹出警示框(显示消息给用户看) 浏览器
console.log(msg) 浏览器控制台打印输出信息(显示消息给程序员看) 浏览器
prompt(info) 浏览器弹出输入框(用户可以输入) 浏览器
        // 弹出一个输入框(prompt),让用户输入年龄(用户输入) 并用一个变量保存输入值
        // 把用户输入的值用变量保存起来,把刚才输入的年龄与所要输出的字符串拼接
        // 使用alert语句弹出警示框 输出拼接结果
        var age = prompt('请输入您的年龄');
        var str = '您今年已经' + age + '岁了';
        alert(str);

三.JavaScript 变量

1.定义变量

  • 变量:用于存放数据的容器,通过 变量名 获取 / 修改数据。
  • 变量本质:是内存里的一块空间,用来存储数据。

2.使用变量

  • 声明变量 var:计算机会自动为变量分配内存空间。
  • 变量名 xx:通过变量名访问内存中分配的空间。
  • 变量初始化:声明一个变量并赋值(如 var age = 18;)。
  • 声明多个变量:写一个 var, 多个变量名间用 英文逗号 隔开 并 换行(如var age = 10,  name = 'xyc', sex = 2;   )。
var age = 10,  
    name = 'xyc', 
    sex = 2;  
  • 特殊情况:
    情况 说明 结果

    var age ; console.log (age);

    只声明 不赋值 undefined
    console.log(age) 不声明 不赋值 直接使用 报错
    age = 10; console.log (age); 不声明 只赋值  10
  • 交换两个变量的值:
            // 1. 把apple1 的值给临时变量 temp 
            // 2. 把apple2 的值给 apple1 
            // 4. 把temp 的值给 apple2 
            var temp; // 声明了一个临时变量 为空
            var apple1 = '青苹果';
            var apple2 = '红苹果';
            temp = apple1; // 把右边给左边
            apple1 = apple2;
            apple2 = temp;

四.JavaScript 数据类型

1.数据类型定义

  • 数据类型决定了如何将代表这些值的位存储到计算机的内存中。
  • JavaScript 是一种弱类型 / 动态语言。即不用提前声明变量类型,程序运行过程中,类型会被自动确定。
  • JS 是动态语言,变量的数据类型是 可以变化 的。
        // js是动态语言 变量的数据类型是可以变化的
        var x = 10; // x 是数字型 
        x = 'pink'; // x 字符串型

2.数据类型分类

  • JS 数据类型分为两类:
  1. 简单数据类型 (Number,String,Boolean,Undefined,Null)
  2. 复杂数据类型 (object)

3.数字型 Number

3.1 JavaScript 中数值的最大和最小值

  • 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
  • 最小值:Number.MIN_VALUE,这个值为:5e-32

3.2 数字型三个特殊值

  • Infinity :代表无穷大,大于任何数值。
  • -Infinity :代表无穷小,小于任何数值。
  • NaN :Not a number,代表一个非数值。
  • isNaN():判断变量是否为 非数值,返回 true 或 false。
        console.log(Number.MAX_VALUE);
        console.log(Number.MIN_VALUE);

        console.log(Number.MAX_VALUE * 2); // Infinity 无穷大  
        console.log(-Number.MAX_VALUE * 2); // -Infinity 无穷小

        console.log('pink老师' - 100); // NaN 非数值
        console.log(isNaN(12)); // false 不是非数值
        console.log(isNaN('黄焖鸡米饭')); // true 是非数值

4.字符串型 String

  • ​JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)。
  • 不加引号会报错,HTML 使用 双引号,所以 JS 推荐 单引号。
var strMsg = '我是"高帅富"程序猿';   // 可以用''包含""
var strMsg2 = "我是'高帅富'程序猿";  // 也可以用"" 包含''
  • 字符串转义字符:
    转义符 解释说明
    \n 换行符,n 是 newline 的意思
    \ \ 斜杠 \
    \t tab 缩进
    \b 空格 ,b 是 blank 的意思
  • 字符串长度:string.length
  • 字符串相连:字符串 + 任何类型 = 拼接之后的新字符串,看下面1.3
//1.1 字符串 "相加"
alert('hello' + ' ' + 'world'); // hello world
//1.2 数值字符串 "相加"
alert('100' + '100'); // 100100
//1.3 数值字符串 + 数值
alert('11' + 12);     // 1112 
//1.4 数值 + 数值
alert(11 + 12);     // 23 

5.布尔型 Boolean

console.log(true + 1);  // 2    true相当于1
console.log(false + 1); // 1    false相当于0

6.Undefined 和 Null

  • ​ 一个变量 声明后没有被赋值:会有默认值 undefined ( 相连【字符串+undefined】、相加【NaN】)。
var variable;
console.log(variable);           // undefined
console.log('你好' + variable);  // 你好undefined
console.log(11 + variable);     // NaN
console.log(true + variable);   //  NaN
  • ​ 一个变量 声明后给 null 值:里面存的值为空(相连【字符串+null】、相加【其他变量不变】 区分对象部分 null)。
var vari = null;
console.log('你好' + vari);  // 你好null
console.log(11 + vari);     // 11
console.log(true + vari);   //  1

7.获取变量数据类型​ (typeof 变量名)

  • prompt 取过来的值是 字符型的。
        // prompt 取过来的值是 字符型的
        var age = prompt('请输入您的年龄');
        console.log(typeof age);    //结果为 String  
  • typeof null 是非常特殊的,他返回的是"object"  

8.数据类型转换

8.1 转换为字符串

  • 三种转换方式:变量.toString()、String(变量) 、利用 + 拼接字符串 实现转换(隐式转换)。
  • 更多用第三种 加号拼接字符串 转换方式, 这一种方式也称为隐式转换。
    <script>
        // 1. 变量.toString()
        var num = 10;
        var str = num.toString();
        console.log(str);
        // 2. String(变量)   
        console.log(String(num));
        // 3. 利用 + 拼接字符串 实现转换效果 隐式转换
        console.log(num + '');
    </script>

8.2 转换为数字型(重点)

  • parseInt(变量)  可以把 字符型的转换为数字型 得到是 整数,注意 parseInt 和 parseFloat 大小写。
  • parseFloat(变量) 可以把 字符型的转换为数字型 得到是 浮点数,注意 parseInt 和 parseFloat 大小写。
  • 上面两种方式不会四舍五入 可以去除数字开头的单位。
  • Number(变量) 
  • 利用算数运算 -  *  /  隐式转换
    <script>
        var age = prompt('请输入您的年龄'); 前面说了prompt 获取的用户输入数据是 String 类型

        // 1. parseInt(变量)  可以把 字符型的转换为数字型 得到是 整数
        console.log(parseInt(age));
        console.log(parseInt('3.14')); // 3 取整
        console.log(parseInt('3.94')); // 3 取整 不会四舍五入
        console.log(parseInt('120px')); // 120 会去到这个px单位
        console.log(parseInt('rem120px')); // NaN 数字在最前面 否则不能去除单位

        // 2. parseFloat(变量) 可以把 字符型的转换为数字型 得到是 浮点数
        console.log(parseFloat('3.14')); // 3.14
        console.log(parseFloat('120px')); // 120 会去掉这个px单位
        console.log(parseFloat('rem120px')); // NaN

        // 3.  Number(变量) 
        var str = '123';
        console.log(Number(str));
        console.log(Number('12'));

        // 4. 利用算数运算 -  *  /  隐式转换
        console.log('12' - 0); // 12
        console.log('123' - '120');
        console.log('123' * 1);
    </script>
  • 计算年龄实例: 
var year = prompt('请您输入您的出生年份');    //(用户输入)
var age = 2020 - year; // year 取过来的是字符串型 这里用减法 有隐式转换(程序内部处理)
alert('您今年已经' + age + '岁了');    //(输出结果)
  • 加减计算实例:
        var num1 = prompt('请您输入第一个值:');
        var num2 = prompt('请您输入第二个值:');
        var result = parseFloat(num1) + parseFloat(num2);    //此处转换为数字类型
        alert('您的结果是:' + result);

 8.3 转换为布尔型

  • 代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined
  • 其余值都会被转换为 true
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('比特是狗')); // true
console.log(Boolean(12)); // true

五.标识符、关键字、保留字

1.解释型语言和编译型语言

  • 翻译器翻译的方式有两种:一个是编译,一个是解释。两种方式区别在于翻译的时间点不同。
  • 编译器:在 代码执行之前 进行编译,生成中间代码文件(如 Java 中的 .class 文件)。
  • 解释器:在 运行时 进行解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)。

2.标识符

  • 指开发人员为变量、属性、函数、参数取的名字,不能是关键字或保留字。

3.关键字

  • 指 JS 本身已经使用了的字,不能再用它们充当变量名、方法名。
  • 包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。

4.保留字

  • 指预留的“关键字”,现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
  • 包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
  • 注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则可能收不到任何错误消息。

六.JavaScript 运算符(操作符)

1.运算符(操作符)分类

  • 算数运算符
  • 递增和递减运算符
  • 比较运算符
  • 逻辑运算符
  • 赋值运算符

2.算数运算符

浮点数的精度问题

浮点数值的最高精度是 17 位小数,但进行算术计算时 精确度 远不如整数。

所以:不要直接判断两个浮点数是否相等 !

var result = 0.1 + 0.2;    // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100);   // 结果不是 7,而是:7.000000000000001

// 不能直接拿着浮点数进行比较 
var num = 0.1 + 0.2;
console.log(num == 0.3); // false

3.递增和递减运算符

3.1 前置递增运算符(先自加,后返回值)

var  num = 10;
alert(++num + 10);     //21
//先执行 ++num 这个表达式,使之结果为11
//再执行 ++num + 10 这个表达式,使之结果为21 

3.2 后置递增运算符(先返回原值,后自加)

var  num = 10;
alert(10 + num++);    // 20
//先执行 10 + num++ 这个表达式,使之结果为20,此时是 num++ = 10 参与计算
//再执行 num++ 这个表达式,使之结果为11

3.3 练习 

        var e = 10;
        var f = e++ + ++e; // 1. e++ =  10  e = 11  2. e = 12  ++e = 12
        console.log(f); // 22
        // e++:e 本身先不变化,e++ 运算得到10,e 在 e++ 算完后自加得到 11,e=11参与下面的运算
        // ++e:e 本身先变化 得到 12,++e 运算得到 12 

4.比较运算符

  • 程序里的等于符号 是 ==  默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以。
  • 程序里面有全等 要求 两侧的值 还有 数据类型完全一致。
        //1. 程序里的等于符号 是 ==  默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以
        console.log(18 == '18'); // true
        console.log('茶茶子' == '不喜欢特特'); // flase

        // 2. 程序里面有全等 要求 两侧的值 还有 数据类型完全一致
        console.log(18 === 18); // true
        console.log(18 === '18'); // false

5.逻辑运算符

  • 分类:逻辑与&&、逻辑或||、逻辑非!
  • 短路运算(逻辑中断):当有多个表达式时,假设左边表达式可以确定结果,就不再继续运算右边的表达式。
  • 逻辑与:表达式1 && 表达式2,左真返右,左假返左。(简单理解:一个为假就是假)
//如果 表达式1 的值为真,则返回 表达式2
//如果 表达式1 的值为假,则返回 表达式1
// 如果有空的或者否定的为假 其余是真的  0  ''  null undefined  NaN
console.log( 123 && 456 );        // 456
console.log( 0 && 456 );          // 0
console.log('' && 1 + 2 && 456 * 56789); // ''
  •  逻辑或:表达式1 || 表达式2,左真返左,左假返右。(简单理解:一个为真就是真)
//如果 表达式1 的值为真,则返回 表达式1
//如果 表达式1 的值为假,则返回 表达式2
console.log( 0 ||  456 );          //  456
console.log( 123 || 456 || 789 );  //  123

6.赋值运算符

var age = 10;
age += 5;  // 相当于 age = age + 5;
age *= 10; // 相当于 age = age * 10;

7.运算符优先级

七.JavaScript 流程控制

1.流程控制三种结构

  • 顺序结构、分支结构、循环结构。

2.顺序流程控制

  • 程序会按照代码的 先后顺序,依次执行。

3.分支流程控制

3.1 分支结构定义

  • 根据不同条件,执行不同路径代码(执行代码多选一的过程),得到不同结果。
  • JS 提供两种分支结构语句:if 语句、switch 语句。

3.2 if 语句

3.2.1 if

if (条件表达式) {
    // 条件成立执行的代码语句 否则什么也不做
}

3.2.2 if else(双分支)  判断闰年案例

        var year = prompt('请您输入年份:');
        if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
            alert('您输入的年份是闰年');
        } else {
            alert('您输入的年份是平年');
        }

3.2.3 if else if(多分支)  判断成绩案例

// 按照从大到小的思路来写     
   var score = prompt('请您输入分数:');
        if (score >= 90) {
            alert('宝贝,你是我的骄傲');
        } else if (score >= 80) {
            alert('宝贝,你已经很出色了');
        } else if (score >= 70) {
            alert('你要继续加油喽');
        } else {
            alert('等着挨打吧');
        }

3.3 三元表达式

  • 表达式1 ? 表达式2 : 表达式3
  • 1真执行2,1假执行3,类似于if else (双分支) 的简写。
  • 时间数字补 0 案例
        var time = prompt('请您输入一个 0 ~ 59 之间的一个数字');
        var result = time < 10 ? '0' + time : time; //   把返回值赋值给一个变量
        alert(result);

3.4 switch 语句

  • 当要针对变量设置一系列的 固定值 的选项时,使用 switch。
  • switch :开关 转换 , case :小例子 选项
  • 执行 case 里面的语句时,如果没有break,则继续执行下个 case 里面的语句。
  • switch 中的值 必须和 case 中的值 全等=== 即 数值+类型 完全相同。
  • 查询水果案例
// case 后面的值写水果名称,一定要加引号 ,因为必须是全等匹配。
        var fruit = prompt('请您输入查询的水果:');
        switch (fruit) {
            case '苹果':
                alert('苹果的价格是 3.5/斤');
                break;
            case '榴莲':
                alert('榴莲的价格是 35/斤');
                break;
            default:
                alert('没有此水果');
        }

3.5 switch 语句和 if else if 语句的区别

  • switch 语句通常处理 case 为 确定值 的情况, 而 if…else…语句更加灵活,常用于 范围判断。
  • switch 语句仅执行符合条件的代码,效率更高。而if…else 语句所有条件代码都得执行,效率不如前者。
  • 当分支比较少时,if… else 语句的执行效率高。
  • 当分支比较多时,switch 语句的执行效率高,而且结构更清晰。

4.循环流程控制

4.1 for 循环(与计数有关)

4.1.1 for 循环重复 相同 的代码

var num = prompt('请输入次数:');
for ( var i = 1 ; i <= num; i++) {
    console.log('特特喜欢茶茶');
} 

4.1.2 for 循环重复 不相同 的代码

for (var i = 1; i <= 100; i++) {
 if (i == 1) {
    console.log('特特今年1岁了, 他出生了');
 } else if (i == 100) {
    console.log('茶茶今年100岁了,她死了');
  } else {
       console.log('他们今年' + i + '岁了');
  }}

4.1.3 断点调试过程

  • 浏览器中按 F12 --> sources --> 找到需要调试的文件 --> 在程序的某一行设置断点。
  • Watch:监视,通过 watch 可以监视变量的值的变化,非常常用。
  • 浏览器中按 F11,让程序一行一行的执行,观察 watch 中变量的值的变化。
  • 班级平均成绩案例
        var num = prompt('请输入班级的总人数:'); // num 总的班级人数
        var sum = 0; // 求和的变量
        var average = 0; // 求平均值的变量
        for (var i = 1; i <= num; i++) {
            var score = prompt('请您输入第' + i + '个学生成绩');
            // 因为从prompt取过来的数据是 字符串型的需要转换为数字型
            sum = sum + parseFloat(score);
        }
        average = sum / num;
        alert('班级总的成绩是' + sum);
        alert('班级平均分是:' + average);

4.2 双重 for 循环

  • 外层循环执行一次,内层循环要执行全部次数。
  • 打印 n行n列 星星案例(逻辑:内层循环负责打印一行 n个 星星,外层循环负责打印 n行)
        var rows = prompt('请您输入行数:');    // 行
        var cols = prompt('请您输入列数:');    // 列
        var str = '';    // 原来的星星是 一个空的字符串
        for (var i = 1; i <= rows; i++) {    // 外层循环 负责打印总行数
            for (var j = 1; j <= cols; j++) {    // 内层循环 负责打印每行个数
                str = str + '★';    // 在空字符串基础上不断链接星星字符串
            }
            str += '\n';    // 打印了一行星星之后 记得给这行追加换行符号
        }
        console.log(str);
  • 打印乘法表案例(逻辑:外层循环负责行数,内层循环负责每行公式,每行公式的个数 = 行数, j <= i;)
        // 外层的 for 循环控制行数 i ,循环9次 ,可以打印 9 行  
        // 内层的 for 循环控制每行公式  j  
        // 核心算法:每一行 公式的个数正好和行数一致, j <= i;
        // 每行打印完毕,都需要重新换一行
        var str = '';    // 最初的乘法表是空的
        for (var i = 1; i <= 9; i++) { // 外层循环 控制行数 i,打印9行
            for (var j = 1; j <= i; j++) { // 内层循环 控制每行公式个数 j  j = i
                str += j + '×' + i + '=' + i * j + '\t';    // 空字符串追加乘法公式
            }
            str += '\n';    // 打印完一行乘法公示后记得换行
        }
        console.log(str);

输出结果: 

4.3 while 循环

  • 使用 while 循环时一定要有 退出条件(完成计数器更新),否则会成为死循环。
        var num = 1;    // 计数器 初始化变量
        while (num <= 100) {
            console.log('特特喜欢茶茶');
            num++;    // 操作表达式  完成计数器的更新 防止死循环
        }

4.4 do-while 循环

// 至少执行一次
do {
    var message = prompt('特特你喜欢我吗?');
    } while (message !== '我喜欢你')
alert('我也喜欢你ww');

4.5 区分 continue、break

  • continue 关键字 退出本次(当前次的循环)  继续执行剩余次数循环
  • break 关键字 退出整个循环
  • 求除了能被7整除之外的整数的和案例(continue应用)
        var sum = 0;
        for (var i = 1; i <= 100; i++) {
            if (i % 7 == 0) {
                continue;     // 只要遇见 continue就退出本次循环 直接跳到 i++
            }
            sum += i;
        }
        console.log(sum);

八.JavaScript 数组

1.数组定义

  • 数组是指 一组数据的集合,其中的每个数据被称作 元素,在数组中可以 存放任意类型的元素
  • 数组是一种将一组数据存储在单个变量名下的 优雅方式。

2.创建数组

  • 利用 new 创建数组
// 创建一个新的空数组,注意 Array(),A 要大写
var arr = new Array();   
  • 利用 数组字面量 创建数组(使用最多)
// 使用 数组字面量方式 创建数组
var  数组名 = [];    // 创建了一个空的数组
var  cute = ['一只特特','一只茶茶','一只桃西西'];    // 数组元素用逗号间隔
  • 数组元素的类型:数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。
var arrStus = ['茶茶',20,true];

3.获取数组中的元素

  • 数组通过索引操作对应的数组元素:数组名[索引号],索引号从 0 开始。
  • 如果访问时数组没有和索引号对应的元素,则输出值是 undefined。
var arrStus = [1,2,3];    // 定义数组
alert(arrStus[1]);    // 获取数组中的第2个元素
alert(arrStus[3]);     // 没有这个数组元素 输出的结果是 undefined

4.遍历数组

4.1 数组遍历(for 循环)

var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){    // 数组索引号从0开始 ,所以 i 必须从 0 开始
    console.log(arrStus[i]);    // arr.length 动态监测数组元素的个数 方便随时追加并遍历
}

4.2 数组的长度(指数组元素的个数)

  • 数组的 length 属性可以被修改。
  • 如果 length 大于数组元素个数,则会在数组末尾追加空白元素。
  • 如果 length 小于数组元素个数,则会把超过的数组元素删除。
  • 数组索引号和数组长度: 索引号从 0 开始是 下标, 数组长度是 元素个数。
        // 将数组 ['red', 'green', 'blue', 'pink'] 转换为字符串,并且用 | 或其他符号分割
        var arr = ['red', 'green', 'blue', 'pink'];
        var str = '';    // 采用字符串追加的方式 实现数组到字符串的转换
        var sep = '|';    // 分割符号变量 
        for (var i = 0; i < arr.length; i++) {    // 遍历数组
            str += arr[i] + sep;    // 给空字符串追加 数组元素 以及 分割符号
        }
        console.log(str);

5.数组中新增元素

  • ① 修改 length 长度
        // 1. 新增数组元素 修改length长度 
        var arr = ['red', 'green', 'blue'];    // 此时数组长度是3
        arr.length = 5;     // 数组的长度修改为了 5  里面应该有5个元素 
        console.log(arr);    //会有五个元素 但其中两个因为是空的不显示
        console.log(arr[3]);     // undefined
        console.log(arr[4]);     // undefined
  • ② 修改索引号,追加数组元素
        // 2. 新增数组元素 修改索引号 追加数组元素
        var arr1 = ['red', 'green', 'blue'];
        arr1[3] = 'pink';
        arr1[4] = 'hotpink';
        arr1[0] = 'yellow'; // 这里是替换原来的数组元素
        console.log(arr1);
        arr1 = '就这?';
        console.log(arr1); // 不要直接给 数组名赋值 否则里面的数组元素都没有了

6.筛选数组元素

  • 将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。
  • 思路:声明新数组,遍历旧数组,用 新数组[新数组长度] 来给新数组追加符合要求的数组元素。
        var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
        var newArr = [];    // 1、声明一个新的数组用于存放新数据newArr。
        for (var i = 0; i < arr.length; i++) {    // 2、遍历原来的旧数组, 找出大于等于 10 的元素。
            if (arr[i] >= 10) {
                newArr[newArr.length] = arr[i];      // 3、刚开始 newArr.length 就是 0依次追加给新数组 newArr 追加之后 newArr.length 会自动改变
            }
        }
        console.log(newArr);

7.数组元素去重

  • 将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组。
  • 思路:声明新数组,遍历旧数组,用 新数组[新数组长度] 来给新数组追加符合要求的数组元素。
        // 3、新数组里面的个数, 用 length 不断累加。
        var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
        var newArr = [];    // 1、新建一个数组用于存放筛选之后的数据
        for (var i = 0; i < arr.length; i++) {    // 2、遍历原来的数组
            if (arr[i] != 0) {
                newArr[newArr.length] = arr[i];    // 3、把不是 0 的数据添加到新数组里
            }
        }
        console.log(newArr);

8.数组翻转

  • 将数组 ['red', 'green', 'blue', 'pink', 'purple'] 的内容反过来存放
  • 思路:反过来遍历原数组
        var arr = ['red', 'green', 'blue', 'pink', 'purple', 'hotpink'];
        var newArr = [];     // 1、声明一个新数组 newArr
        for (var i = arr.length - 1; i >= 0; i--) {    //2、反过来遍历原来的数组
            newArr[newArr.length] = arr[i]    
        }
        console.log(newArr);

9.冒泡排序

        var arr = [4, 1, 2, 3, 5];
        for (var i = 0; i <= arr.length - 1; i++) { // 外层循环趟数 
            for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环 每一趟的交换次数
                // 内部交换2个变量的值 前一个和后面一个数组元素相比较
                if (arr[j] < arr[j + 1]) {
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        console.log(arr);

九.JavaScript 函数

1.函数定义

  • 函数:封装了一段 可被重复调用执行 的代码块。

2.函数的使用(声明+调用)

2.1 声明函数

// 声明函数 function 关键字,必须小写
function 函数名() {    // 函数名命名一般是动词
    // 函数体代码
}

2.2 调用函数

  • 调用函数不要忘记添加小括号:函数名();

  • 声明函数 本身并不会执行代码,只有 调用函数 时才会执行 函数体代码。

2.3 函数封装

  • 函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
// 声明函数 不执行代码
function getSum(){
  var sumNum = 0;// 准备一个变量,保存数字和
  for (var i = 1; i <= 100; i++) {
    sumNum += i;// 把每个数值 都累加 到变量中
  }
  alert(sumNum);
}
// 调用函数 执行代码
getSum();

3.函数的参数

3.1 函数参数语法

  • 调用的时候 实参 传递给 形参。
  • 形参默认值 undefined。
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
  // 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...); 

3.2 函数形参和实参数量不匹配时

  • 函数可以带参数也可以不带参数。
  • 声明函数的时候,函数名括号里面的是形参,形参相当于不用声明的变量。
  • 调用函数的时候,函数名括号里面的是实参。
  • 多个参数中间用逗号分隔。
  • 形参的个数 可以 和实参个数不匹配,但是结果不可预计(undefined / null),尽量要匹配。

4.函数的返回值

  • return 终止函数,并返回指定的值,return 后的代码不执行。
  • 如果函数没有 return ,返回的值是 undefined。
  • return 只能返回一个值,如:return num1, num2; // 返回结果是 最后一个 的值。
  • return 如果想返回多个值,可以考虑数组,如: return [num1 + num2, num1 * num2, num1 / num2];。
  • 实际开发里,经常用一个变量来接受 函数的返回结果 如:var re = getArrMax([5, 2, 99, 101, 67, 77]);。
        function fun1() {
            return 666;
        }
        console.log(fun1()); // 返回 666

        function fun2() {}
        console.log(fun2()); // 返回 undefined
  • break ,continue ,return 的区别:
  1. break :结束当前的循环体(如 for、while)。
  2. continue :跳出本次循环,继续执行下次循环(如 for、while)。
  3. return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码。

5.arguments 的使用

  • 只有函数才有 arguments 对象  而且是每个函数都内置好了 arguments。
  • 当不确定有多少个参数传递的时候,可以用 arguments 来获取。
  • arguments 对象中存储了传递的 所有实参,在函数内部使用。
  • arguments 是一个伪数组,因此 可以遍历。
  • 关于伪数组:
  1. 具有 length 属性
  2. 按索引方式储存数据
  3. 不具有数组的 push() , pop() 等方法
// 利用函数求任意个数的最大值(不确定输入数,考虑 arguments)
     function getMax() { //里面存储了所有实参 arguments = [1,2,3] + arguments = [1, 2, 3, 4, 5]...
            var max = arguments[0];    // 设第一个元素为最大值
            for (var i = 1; i < arguments.length; i++) {    // arguments.length
                if (arguments[i] > max) {    // 可以按照数组的方式遍历 arguments
                    max = arguments[i];
                }
            }
            return max;
        }
        console.log(getMax(1, 2, 3));
        console.log(getMax(1, 2, 3, 4, 5));

6.函数案例

6.1 判断二月天数

  • 利用知识点:函数可以互相调用
        // 用户输入年份,输出当前年份2月份的天数
        function backDay() {
            var year = prompt('请您输入年份:');
            if (isRunYear(year)) { // 只有是闰年时 才是true if分支才可以执行 
                alert('当前年份是闰年2月份有29天');
            } else {
                alert('当前年份是平年2月份有28天');
            }
        }
        backDay();    //先执行这个方法调用 再跳转到上面的函数 再通过上面的函数调用下面的函数


        // 判断是否为闰年的函数
        function isRunYear(year) {
            // 如果是闰年我们返回 true  否则 返回 false 
            var flag = false;
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                flag = true;
            }
            return flag;
        }

6.2 利用函数书写冒泡排许

        // 利用函数冒泡排序 sort 排序
        function sort(arr) {
            for (var i = 0; i < arr.length - 1; i++) {
                for (var j = 0; j < arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {
                        var temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
        var arr1 = sort([1, 4, 2, 9]);
        console.log(arr1);
        var arr2 = sort([11, 7, 22, 999]);
        console.log(arr2);

7.函数的两种声明方式

7.1 自定义函数方式 ( 命名函数 )

// 声明定义方式
function fn() {}
// 调用  
fn();  
  • 函数调用的代码 既可以放到声明函数的前面,也可以放在声明函数的后面。

7.2 函数表达式方式 ( 匿名函数)

// 函数表达式写法,匿名函数后面跟分号结束,类似于变量声明
var fn = function(){};
// 调用的方式,函数调用 必须写到 函数体下面
fn();    //fn是变量名,不是函数名
  • 类似于声明变量,存储值是函数,里面的函数是没有名字的,fn 指得是变量名字,记得分号。
  • 函数调用的代码 必须 写到函数体后面。

十.JavaScript 作用域

1.全局作用域和局部作用域

  • 全局作用域:作用于所有代码执行的环境。
  • 局部作用域:作用于函数内的代码环境,也称为函数作用域。
  • 目的:减少命名冲突。
  • JS 没有块级作用域 {}(ES6之前)
if(true){
  int num = 123;
  system.out.print(num);  // java输出:123  js输出:123
}
system.out.print(num);    // java输出:报错  js输出:123

// java代码会报错,因为代码中 {} 即一块作用域,其中声明的变量 num,在 “{}” 之外不能使用
// js中没有块级作用域(在ES6之前)

2.全局变量和局部变量 

  • 在全局作用域下声明的变量 是全局变量 :任何位置都可以使用 浏览器关闭时才会被销毁 比较占内存。
  • 如果在函数内部 没有声明(写 var),直接赋值 的变量也属于全局变量(不建议使用)。
  • 在函数内部声明的变量 是局部变量 :只能在该函数内部使用 代码结束就销毁 节约内存。
  • 函数的形参实际上就是局部变量。
        var num = 10;    // num 是全局变量 任何位置都能使用
        function fun(aru) {
            var num1 = 10;    // num1 是局部变量 只能在函数内部使用
            num2 = 20;    // 因为没使用函数声明var 就直接赋值 所以即使在函数内部 num2 依旧是全局变量
        }

3.作用域链

  • 采取 就近原则 方式来查找变量最终值。
        var a = 1;    
        function fn1() {
            var a = 2;
            var b = '22';
            fn2();
            function fn2() {
                var a = 3;
                fn3();
                function fn3() {
                    var a = 4;
                    console.log(a); //a的值 ? 4 就近
                    console.log(b); //b的值 ? 字符串22 就近
                }
            }
        }
        fn1();    

十一.JavaScript 预解析

1.预解析定义

  • 把 变量和函数 的声明 在代码执行之前执行完成,也叫变量 / 函数提升。

2.变量预解析

  • 变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。

3.函数预解析

  • 函数提升(函数预解析): 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

4.案例解析

         var num = 10;
         fun();

         function fun() {
             console.log(num);
             var num = 20;
        }

        // 相当于执行了以下操作
        // var num;    // 变量声明提升
        // function fun() {    // 函数声明提升
        //     var num;    // 函数内部变量声明提升
        //     console.log(num);    // 函数内部代码顺序执行 控制台输出
        //     num = 20;    // 函数内部代码顺序执行 赋值
        //  }
        // num = 10;    // 外部函数顺序执行 赋值
        // fun();    // 外部函数顺序执行 调用内部函数

5.关于集体声明 和 预解析

f1();
        console.log(c);
        console.log(b);
        console.log(a);

        function f1() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        // 相当于以下代码
        // function f1() {
        //     var a;
        //     a = b = c = 9;
        //     // 相当于 var  a  = 9; b = 9; c = 9; 
        //     // b 和 c 直接赋值 没有var 声明 当全局变量看
        //     // 集体声明  var a = 9, b = 9, c = 9;
        //     console.log(a);
        //     console.log(b);
        //     console.log(c);
        // }
        // f1();
        // console.log(c);
        // console.log(b);
        // console.log(a);

十二.JavaScript 对象

1.使用字面量创建对象(键值对)

var obj = {};  // 创建了一个空的对象 
var MeowMeowTea = {
    name : 'MeowMeowTea',    // 键:属性名  值:属性值 
    age : 20,    // 多个属性 用逗号隔开
    sex : '女',
    sayHi : function(){    // 这是匿名函数
        alert('茶茶喜欢特特');
    }
};    // 不要忘记;

2.使用对象

  • 对象包括 属性 和 方法
  • 对象属性调用①:对象.属性名 ,这个小点 . 理解为“ 的 ”。
  • 对象属性调用②:对象[‘属性名’],方括号里面的属性必须加引号。
  • 对象方法调用:对象.方法名() ,方法名字后面一定加括号。
console.log(MeowMeowTea.name);     // 调用名字属性 注意小点
console.log(MeowMeowTea['name']);  // 调用名字属性 注意方括号单引号
MeowMeowTea.sayHi();    // 调用方法 记得别忘记()
  • 区分 变量、属性、函数、方法:
  • 变量 / 函数:单独声明赋值,单独存在,不是对象的一部分。
  • 属性 / 方法:对象里面的变量称为属性,不需要声明,是对象的一部分。

3.使用 new Object 创建对象

var s = new Obect();    // Object() :第一个字母大写 此时创建了一个空对象
s.name = 'Tea';    // 利用 = 赋值的方法 添加对象的属性和方法
s.age = 20;    // 每个属性和方法之间用 分号 结束
s.sex = '女';
s.sayHi = function(){
    alert('特特喜欢茶茶');
}

4.使用构造函数创建对象(对象实例化)

  • 使用构造函数的原因:把对象里 相同的属性和方法 抽象出来 封装到 函数 里,减少重复代码。
  • 前面两种方法每次只能创建一个对象,构造函数每次可创建多个对象。
  • 构造函数约定 首字母大写
  • 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
  • 构造函数中 不需要 return 返回结果
  • 创建对象的时候,必须用 new 来调用构造函数
        function Star(uname, age, sex) {  // 1. 构造函数名字首字母要大写
            this.name = uname;    // 属性和方法前面必须添加 this
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);
            }
        }
        var obj1 = new Star('茶茶子', 20, '女');   // 用 new 调用函数返回的是一个对象
  • new关键字的作用:
  1. 在构造函数代码开始执行之前,创建一个空对象;
  2. 修改this的指向,把 this 指向创建出来的空对象;
  3. 执行构造函数里面的代码,给这个空对象添加属性和方法;
  4. 在函数完成之后,返回 this,即创建出来的对象。

5.遍历对象

for (var k in obj) {    // key 是变量 可以自己改名 obj是对象名字
    console.log(k);      // 这里的 k 是属性名
    console.log(obj[k]); // 这里的 obj[k] 是属性值
}

十三.JavaScript 内置对象

1.内置对象前言

  • ​JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象 (JS 独有)。
  • JS 基础内容包括:自定义对象 + 内置对象,属于 ECMAScript。
  • 内置对象最大的优点:帮助我们快速开发。
  • ​ JavaScript 提供了多个内置对象:Math、 Date 、Array、String 等。
  • 查阅文档:开发者网络(MDN)、W3C。
  • MDN:https://developer.mozilla.org/zh-CN/

2.Math对象(不是构造函数)

  • 不需要实例化 Math (即使用 new 调用)就可以调用里面的属性方法。
属性、方法名 功能
Math.PI 圆周率
Math.floor() 向下取整
Math.ceil() 向上取整
Math.round() 四舍五入 就近取整 注意 -3.5 结果是 -3
Math.abs() 绝对值
Math.max() / Math.min() 求最大和最小值
Math.random() 获取范围在[0,1)内的随机值,含0不含1
获取指定范围内的随机整数(背下来就可以了):
function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}
        // 扩展: 随机点名  
        var arr = ['茶', '御茶', '茶茶子', '夏小朋友', '鲜柠芦荟茶', '特特给我背锅'];
        // 令数组下标是个随机数就可以了
        console.log(arr[getRandom(0, arr.length - 1)]);
  •  寻找最大值、绝对值、取整:
        console.log(Math.max(1, 99, '一只比特')); // NaN
        console.log(Math.max()); // -Infinity

        // 1.绝对值方法 Math.abs()
        console.log(Math.abs(-1)); // 1
        console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型
        console.log(Math.abs('Tea')); // NaN 
 
        // 2.三个取整方法
        // (1) Math.floor()   地板 向下取整  往最小了取值
        console.log(Math.floor(1.1)); // 1
        console.log(Math.floor(1.9)); // 1
        // (2) Math.ceil()   ceil 天花板 向上取整  往最大了取值
        console.log(Math.ceil(1.1)); // 2
        console.log(Math.ceil(1.9)); // 2
        // (3) Math.round()   四舍五入  其他数字都是四舍五入,但是 .5 特殊 它往大了取  
        console.log(Math.round(1.5)); // 2
        console.log(Math.round(-1.5)); // 这个结果是 -1 ∵取大的 -1 > -2

3.日期对象(是构造函数)

  • 需要实例化 Date(使用 new) 才可以调用里面的属性方法。
var now = new Date();    // 没有参数 则获取当前时间

        var date1 = new Date(2019, 10, 1);    // 数字型写法
        console.log(date1);    // 返回的是 11月 不是 10月 
        var date2 = new Date('2019-10-1 8:8:8');    // 字符串型写法
        console.log(date2);
  • 格式化 年月日:
        // 2020年 3月 21日 星期六
        var date = new Date();    // 别忘记 实例化 Date()
        var year = date.getFullYear();    // 返回当前日期的年 2020
        var month = date.getMonth() + 1;    // 返回的月份小1个月 月份+1!!
        var dates = date.getDate();    // 返回的是 几号
        var day = date.getDay();    // 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
        var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
        // 将 周几 作为数组索引号 实现 数字到汉字 的转换
        console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
  • 格式化 时分秒: 
        // 封装一个函数返回当前的时分秒 格式 08:08:08
        function getTimer() {
            var time = new Date();    // 别忘记 实例化 Date()
            var h = time.getHours();    // 时
            h = h < 10 ? '0' + h : h;    // 利用三元表达式 在时间不是两位数时 补0
            var m = time.getMinutes();    // 分
            m = m < 10 ? '0' + m : m;
            var s = time.getSeconds();    // 秒
            s = s < 10 ? '0' + s : s;
            return h + ':' + m + ':' + s;
        }
        console.log(getTimer());
  • 总毫秒数的含义:基于1970年1月1日(世界标准时间)起的毫秒数。
  • 获取总毫秒数(时间戳):
var now = new Date();    // 实例化Date对象

console.log(date.valueOf())	    // 1. 用于获取对象的原始值
console.log(date.getTime())	    // 1. 用于获取对象的原始值

var now = +new Date();		// 2. 简单写可以这么做(最常用写法) +new Date()	

var now = Date.now();    // 3. HTML5 中提供的方法,有兼容性问题
  • 倒计时效果 (原理:时间戳、时间格式化):
        // 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 
        // 2.用时间戳来做:用户输入时间总的毫秒数减去现在时间的总的毫秒数
        // 3.剩余时间总毫秒数 转换为天、时、分、秒 (时间戳转换为时分秒)

        function countDown(time) {
            var nowTime = +new Date(); // 当前时间总的毫秒数
            var inputTime = +new Date(time); // 用户输入时间总的毫秒数
            var times = (inputTime - nowTime) / 1000; // 剩余时间总的秒数 
            var d = parseInt(times / 60 / 60 / 24); // 天
            d = d < 10 ? '0' + d : d;
            var h = parseInt(times / 60 / 60 % 24); //时
            h = h < 10 ? '0' + h : h;
            var m = parseInt(times / 60 % 60); // 分
            m = m < 10 ? '0' + m : m;
            var s = parseInt(times % 60); // 当前的秒
            s = s < 10 ? '0' + s : s;
            return d + '天' + h + '时' + m + '分' + s + '秒';
        }
        console.log(countDown('2020-3-22 18:00:00'));

4.数组对象

4.1 创建数组对象的两种方式

  • 4.1.1 字面量方式

var arr = [1,"茶茶子",true];
  • 4.1.2 new Array()

var arr0 = new Array();  // 创建了一个空的数组
var arr1 = new Array(2);  // 这个2 表示 数组的长度为 2  里面有2个空的数组元素 
var arr2 = new Array(2, 3); // 等价于 [2,3]  这样写表示 里面有2个数组元素 是 2和3

4.2 检测是否是数组

  • 4.2.1 instanceof 运算符:可以用来检测是否为数组。

var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
  • 4.2.2 Array.isArray():判断一个对象是否为数组,H5 新增的方法  IE9 以上版本支持。

var arr = [1, 23];
var obj = {};
console.log(Array.isArray(arr));   // true
console.log(Array.isArray(obj));   // false

4.3 添加删除数组元素的方法

  • push(后)、unshift(前) 为 增加 元素方法。
  • pop(后)、shift(前) 为 删除 元素的方法。
        // 1. push() 在数组的末尾 添加一个或者多个数组元素 
        // push 完毕之后,返回的结果是 新数组的长度 
        var arr = [1, 2, 3];
        console.log(arr.push(4, 'tea'));

        // 2. unshift() 在数组的开头 添加一个或者多个数组元素
        // unshift 完毕之后,返回的结果是 新数组的长度 
        console.log(arr.unshift('red', 'purple'));

        // 3. pop() 删除数组的最后一个元素 一次只能删除一个 没有参数
        // pop 完毕之后,返回的结果是 删除的那个元素 
        console.log(arr.pop());

        // 4. shift() 删除数组的第一个元素 一次只能删除一个 没有参数
        // shift 完毕之后,返回的结果是 删除的那个元素 
        console.log(arr.shift());

4.4 数组排序(翻转+排序)

  • sort()方法需要传入参数来设置升序、降序排序。
  • 如果传入“function(a,b){ return a-b;}”,则为升序。
  • 如果传入“function(a,b){ return b-a;}”,则为降序。
        // 1. 翻转数组
        var arr = ['pink', 'red', 'blue'];
        arr.reverse();
        console.log(arr);

        // 2. 数组排序(冒泡排序)
        var arr1 = [13, 4, 77, 1, 7];
        arr1.sort(function(a, b) {
            //  return a - b; 升序的顺序排列
            return b - a; // 降序的顺序排列
        });
        console.log(arr1);

4.5 查找指定数组元素

  • indexOf(数组元素):返回该数组元素的索引号,从 前面 开始查找。
  • lastIndexOf(数组元素) :返回该数组元素的索引号,从 后面 开始查找。
  • 只返回 第一个 满足条件的 索引号,如果找不到 数组元素,则返回的是 -1。
  • 数组去重案例:
 // ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。
        // 1.目标: 把不重复的元素选取出来放到新数组中。
        // 2.核心算法: 遍历旧数组,用旧数组去查询新数组,若该元素在新数组里没出现过,就添加,否则不添加。
        // 3.利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有该元素。

        // 封装一个 去重的函数 unique 独一无二的 
        function unique(arr) {
            var newArr = [];
            for (var i = 0; i < arr.length; i++) {    // 遍历就旧数组
                if (newArr.indexOf(arr[i]) === -1) {    // 在新数组中查询旧数组元素 
                    newArr.push(arr[i]);    // 新数组查不到旧数组元素 就向里添加旧数组元素
                }
            }
            return newArr;    // 别忘记返回新数组
        }
        var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'])
        console.log(demo);

4.6 数组转换为字符串

toString():将数组转化为字符串;join():给数组添加指定分隔符。
        // 1. toString() 将我们的数组转换为字符串
        var arr = [1, 2, 3];
        console.log(arr.toString()); // 1,2,3
        // 2. join(分隔符) 
        var arr1 = ['green', 'blue', 'pink'];
        console.log(arr1.join()); // green,blue,pink
        console.log(arr1.join('-')); // green-blue-pink
        console.log(arr1.join('&')); // green&blue&pink

4.7 其他方法

5.字符串对象

5.1 基本包装类型

  • 基本包装类型:把 简单数据类型 包装成为 复杂数据类型,这样 基本数据类型 就有了 属性和方法。
  • 比如 String 作为简单数数据类型不应该有 length 属性,但实际上它有,因为被 js 包装了。
var temp = new String('Tea');    // 1. 生成临时变量,把简单类型包装为复杂数据类型
str = temp;    // 2. 赋值给声明的字符变量
temp = null;    // 3. 销毁临时变量

5.2 字符串的不可变

  • 在内存中重新给字符串赋值,会重新在内存中开辟空间存新值,变量之前保存的旧值不会被修改,旧值仍占据原来的内存空间,这个特点就是字符串的不可变。 ​
  • 由于字符串的不可变,在 大量拼接字符串 的时候会有效率问题。

5.3 根据字符返回位置

        // 字符串对象  根据字符返回位置  str.indexOf('要查找的字符', [起始的位置])
        var str = '改革春风吹满地,春天来了';
        console.log(str.indexOf('春'));
        console.log(str.indexOf('春', 3)); // 从索引号是 3的位置开始往后查找
  • 查找字符串"abcoefoxyozzopp"中所有 o 出现的位置及次数:
        var str = "oabcoefoxyozzopp";
        var index = str.indexOf('o');    // 查找第一个o出现的位置索引
        var num = 0;    // 用于统计 o 个数
        while (index !== -1) {    // 只要存在 o(indexOf 返回的结果不是 -1 )就一直查找
            console.log(index);    // 打印 o 当前的位置索引
            num++;
            index = str.indexOf('o', index + 1);    // 当前索引加1,从而继续向后查找
        }
        console.log('o 出现的次数是: ' + num);

5.4 根据位置返回字符(重点)

        // 1. charAt(index) 根据位置返回字符
        var str = 'TeaMeow';
        console.log(str.charAt(3));    // M
        // 遍历所有的字符
        for (var i = 0; i < str.length; i++) {
            console.log(str.charAt(i));
        }
        // 2. charCodeAt(index)  返回相应索引号的字符ASCII值 目的: 判断用户按键 
        console.log(str.charCodeAt(0)); // 97
        // 3. str[index] H5 新增的
        console.log(str[0]); // a
  • 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数:
        // 有一个对象 来判断是否有该属性 对象['属性名']
        var o = {
            age: 18
        }
        if (o['sex']) {
            console.log('里面有该属性');
        } else {
            console.log('没有该属性');
        }

        // 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。
        // 核心算法:利用 charAt() 遍历这个字符串
        // 遍历对象,得到最大值和该字符
        var str = 'abcoefoxyozzopp';
        var o = {};    // 创建了一个空对象
        for (var i = 0; i < str.length; i++) {
            var chars = str.charAt(i);     // chars 是字符串的每一个字符
            if (o[chars]) { // o[chars] 得到的是属性值
                o[chars]++;    // 对象存在这个属性 属性出现次数就+1
            } else {
                o[chars] = 1;    // 对象不存在这个属性 属性出现次数就是1
            }
        }
        console.log(o);

        // 2. 遍历对象
        var max = 0;
        var ch = '';
        for (var k in o) {
            if (o[k] > max) {
                max = o[k];    // o[k] 属性值
                ch = k;    // k 属性名
            }
        }
        console.log(max);
        console.log('最多的字符是' + ch);

5.5 字符串操作方法(重点)

  • 追加指定字符串:concat();
  • 截取指定字符串:substr();
        // 1. concat('字符串1','字符串2'....) 追加字符串
        var str = 'Tea';
        console.log(str.concat('red'));    // Teared

        // 2. substr('截取的起始位置', '截取几个字符');
        var str1 = '改革春风吹满地';
        console.log(str1.substr(2, 2));     // 春风
  • 替换指定字符串:replace();
  • 把字符串转换成数组:split();
        // 1. 替换字符 replace('被替换的字符', '替换为的字符')  它只会替换第一个字符
        var str = 'andyandy';
        console.log(str.replace('a', 'b'));    // bndyandy

        // 有一个字符串 'abcoefoxyozzopp'  要求把里面所有的 o 替换为 *
        var str1 = 'abcoefoxyozzopp';
        while (str1.indexOf('o') !== -1) {    // 只要里面能查到字符 o
            str1 = str1.replace('o', '*');    // 就把字符 o 替换成 *
        }
        console.log(str1);

        // 2. 字符转换为数组 split('分隔符')    前面学过 join 把数组转换为字符串
        var str2 = 'red, pink, blue';
        console.log(str2.split(','));
        var str3 = 'red&pink&blue';
        console.log(str3.split('&'));

十四.JavaScript 简单数据类型和复杂数据类型

1.简单数据类型和复杂数据类型

1.1​ 简单类型基本数据类型值类型

  • 在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null。
  • 存放在 栈 里面 里面直接开辟一个空间存放值。

        var timer = null;
        console.log(typeof timer);
        // 简单数据类型 null  返回的是一个空的对象  object
        // 如果有个变量以后打算存储为对象,暂时没想好放啥, 这个时候就给 null 

​1.2 复杂数据类型(引用类型)

  • 在存储时变量中存储的是地址(引用),通过 new 关键字创建的对象,如 Object、Array、Date 等。
  • 首先在 栈 里面存放地址 十六进制表示  然后这个地址指向 堆 里面的数据。

2.堆栈

2.1 堆栈空间分配区别

  • 栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆:存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
  • 简单数据类型的存储方式:值类型变量的数据直接存放在变量(栈空间)中。
  • 复杂数据类型的存储方式: 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中。

3.简单数据类型传参

  • ​函数形参被传送 值类型的实参 时,其实是把变量在 栈 里的值 复制 了一份给形参。
  • 在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) {
    a++;
    console.log(a); 
}
var x = 10;
fn(x);
console.log(x);    // 10

4.复杂数据类型传参

  • ​函数形参被传送 对象类型的实参 时,其实是把变量在 栈 里保存的 堆地址 复制给了形参。
  • 形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象,会互相影响。
function Person(name) {
    this.name = name;
}
function f1(x) { // x = p
    console.log(x.name); // 2. 这个输出什么 ?    茶茶子
    x.name = "狗比特";
    console.log(x.name); // 3. 这个输出什么 ?    狗比特
}
var p = new Person("茶茶子");
console.log(p.name);    // 1. 这个输出什么 ?   茶茶子
f1(p);
console.log(p.name);    // 4. 这个输出什么 ?   狗比特
发布了29 篇原创文章 · 获赞 21 · 访问量 1655

猜你喜欢

转载自blog.csdn.net/Lyrelion/article/details/105022210