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

目录

一.计算机编程基础

二.初识 JavaScript

三.JavaScript 变量

四.JavaScript 数据类型

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

六.JavaScript 运算符(操作符)

七.JavaScript 流程控制

八.JavaScript 数组

九.JavaScript 函数

十.JavaScript 作用域

十一.JavaScript 预解析

十二.JavaScript 对象

十三.JavaScript 内置对象

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


一.计算机编程基础

  • 计算机语言分类:
  • 机器语言(01011),汇编语言(直接对硬件操作,本质01011),高级语言(C、JAVA等)
  • 高级语言必须经过 翻译器 转换,将源代码 二进制化为 机器语言
  • 编程语言和标记语言的区别:
  1. 编程语言:主动的,有很强的逻辑性
  2. 标记语言:不向计算机发出指令,被动的,被读取的
  • 硬盘、内存保存的是 二进制数据;安装软件本质:把程序文件复制到硬盘中
  • 运行软件的过程:打开某程序,先从 硬盘 中把程序代码加载到 内存 中,CPU执行 内存中的代码
  • 数据存储单位:
  1. 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
  2. 字节(Byte):1B = 8b
  3. 太字节(TB): 1TB = 1024GB

二.初识 JavaScript

  • JavaScript 定义:
  • 运行在客户端的脚本语言 (Script 是脚本的意思)
  • 不需要编译,运行过程中由 JS 解释器(JS引擎)【逐行】解释并执行,浏览器本身不执行 JS 代码
  • 浏览器分成两部分:渲染引擎 和 JS 引擎
  1. 渲染引擎:解析HTML与CSS,俗称内核,比如 chrome浏览器的 blink ,老版本的 webkit
  2. JS 引擎:JS 解释器,读取网页中的 JavaScript代码,对其处理后运行,比如 chrome浏览器的 V8
  • JavaScript 作用:
  1. 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
  2. 网页特效
  3. 服务端开发(Node.js)
  4. 桌面程序(Electron)
  5. App(Cordova)
  6. 控制硬件-物联网(Ruff)
  7. 游戏开发(cocos2d-js)
  • JavaScript 组成:
  1. ECMAScript:规定 JS 的基础语法
  2. DOM(文档对象模型):提供接口,对页面上的各种元素进行操作(大小、位置等)
  3. BOM(浏览器对象模型):提供与浏览器窗口进行互动的对象结构,如弹出框、控制浏览器跳转、获取分辨率等
  • JavaScript 输入输出语句:
方法 说明 归属
alert(msg) 浏览器弹出警示框(显示消息给用户看) 浏览器
console.log(msg) 浏览器控制台打印输出信息(显示消息给程序员看) 浏览器
prompt(info) 浏览器弹出输入框(用户可以输入) 浏览器

三.JavaScript 变量

  • 变量:用于存放数据的容器,通过 变量名 获取 / 修改数据
  • 变量本质:是内存里的一块空间,用来存储数据,通过变量名访问这个空间
  • 声明变量 var:计算机会自动为变量分配内存空间
  • 变量初始化:声明一个变量并赋值(如 var age = 18;)
  • 声明多个变量:写一个 var, 多个变量名间,用 英文逗号 隔开并换行(如var age = 10,  name = 'xyc', sex = 2;   )
  • 特殊情况:
    情况 说明 结果

    var age ; console.log (age);

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

四.JavaScript 数据类型

1.数据类型定义

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

2.数据类型分类

  1. 简单数据类型 (Number,String,Boolean,Undefined,Null)
  2. 复杂数据类型 (Object)

3.数字型 Number

  • Number.MAX_VALUE:最大值,这个值为: 1.7976931348623157e+308
  • Number.MIN_VALUE:最小值,这个值为:5e-32
  • Infinity :代表无穷大,大于任何数值,如:Number.MAX_VALUE * 2
  • -Infinity :代表无穷小,小于任何数值,如:-Number.MAX_VALUE * 2
  • NaN :Not a number,代表一个非数值,如:'茶茶子爱吃鸡块'+10086
  • isNaN():判断变量是否为 非数值,返回 true(是非数值) 或 false(是数值)

4.字符串型 String

  • HTML 使用 双引号,所以 JS 推荐 单引号,不加引号会报错
  • 引号嵌套:外双内单,外单内双
  • 字符串 + 其他任何数据类型 = 新字符串:alert('11' + 12);     // 1112 
  • 字符串转义字符:
    转义符 解释说明
    \n 换行符,n 是 newline 的意思
    \ \ 斜杠 \
    \t tab 缩进
    \b 空格 ,b 是 blank 的意思

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】、相加【其他变量不变】)
var vari = null;
console.log('你好' + vari);  // 你好null
console.log(11 + vari);     // 11
console.log(true + vari);   //  1

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

  • prompt() 取过来的值是 字符型的
  • var age = prompt('请输入年龄');
    console.log(typeof age);    // 结果为 String
  • typeof null 是非常特殊的,返回"object" JavaScript 网页编程(一)——JavaScript 基础语法_第1张图片 

8.数据类型转换

8.1 转换为字符串

  • 三种转换方式:
  1. 变量.toString():var str = num.toString();
  2. String(变量) :String(num);
  3. 利用 + 拼接字符串实现转换(隐式转换):console.log(num + '');【最常用】

8.2 转换为数字型(重点)

  1. parseInt(变量) :可以把 字符型 转换为 整数,注意 parseInt 大小写,不会四舍五入 可以去除数字单位
  2. parseFloat(变量) :可以把 字符型 转换为 浮点数,注意 parseFloat 大小写,不会四舍五入 可以去除数字单位
  3. Number(变量) 
  4. 利用算数运算 -  *  /  隐式转换
        var age = prompt('请输入年龄'); 前面说了prompt()获取的是 String类型
        console.log(parseInt(age));
        console.log(parseInt('3.94'));     // 3 取整 不会四舍五入
        console.log(parseInt('120px'));    // 120 会去到这个px单位
        console.log(parseInt('rem120px')); // NaN 数字在最前面 否则不能去除单位

        var str = '123';
        console.log(Number(str));

        console.log('12' - 0); // 12 利用算数运算 +-*/  隐式转换

8.3 转换为布尔型

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

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

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

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

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

  • 标识符:指开发人员为变量、属性、函数、参数取的名字,不能是 关键字、保留字
  • 关键字:指 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 等
  • 保留字:指预留的“关键字”,现在还不是关键字,但未来可能会成为关键字,同样不能当变量名或方法名
  • 保留字包括: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.算数运算符

  • 浮点数精度问题:浮点数值最高精度是 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

2.递增、递减运算符

  • 前置递增运算符(先自加,后返回值)
  • 后置递增运算符(先返回原值,后自加)
var  num = 10;
alert(++num + 10);     // 21
// 先执行 ++num 这个表达式,使之结果为11
// 再执行 ++num + 10 这个表达式,使之结果为21 

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

var e = 10;
var f = e++ + ++e; // 1.e++ =  10  e = 11  2.e = 12  ++e = 12
console.log(f);    // 22

3.比较运算符

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

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

4.逻辑运算符

  • 分类:逻辑与&&、逻辑或||、逻辑非!
  • 短路运算(逻辑中断):当有多个表达式时,假设左边表达式可以确定结果,就不再继续运算右边表达式
  • 逻辑与:表达式1 && 表达式2,左真返右,左假返左。(简单理解:一个为假就是假)
// 如果有空的或者否定的为假 其余是真的  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

5.赋值运算符

七.JavaScript 流程控制

  • 流程控制三种结构:顺序结构、分支结构、循环结构
  • 顺序流程控制:程序按照代码的 先后顺序,依次执行

1.分支流程控制

  • 分支流程控制:根据不同条件,执行不同路径代码,得到不同结果
  • 两种分支结构语句:if 语句、switch 语句
  • if else(双分支)  判断闰年:
        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;}
  • if else if(多分支)  判断成绩:成绩从大往小写
       var score = prompt('请您输入分数:');
        if (score >= 90) {
            alert('宝贝,你是我的骄傲');
        } else if (score >= 80) {
            alert('你已经很出色了');
        } else if (score >= 70) {
            alert('你要继续加油');
        } else {
            alert('等着挨打吧');
        }
  • 三元表达式:表达式1 ? 表达式2 : 表达式3,1真执行2,1假执行3
  • 时间补0:
        var time = prompt('请输入 0-59 之间的一个数字');
        var result = time < 10 ? '0' + time : time; 
        alert(result);
  • switch 语句:对变量设置 固定值 的选项时,使用 switch
  • switch :开关 转换 , case :小例子 选项
  • 执行 case 里面的语句时,如果没有break,则继续执行下个 case里面的语句
  • switch中的值 必须和 case中的值 全等===,即 数值+类型 完全相同
  • 查询水果:
        // case 后面的值写水果名称,一定要加引号 ,因为必须全等匹配
        var fruit = prompt('请您输入查询的水果:');
        switch (fruit) {
            case '苹果':
                alert('苹果的价格是 3.5/斤');
                break;
            default:
                alert('没有此水果');
        }
  • switch 语句和 if else if 语句的区别:
  1. switch 语句通常处理 case 为 确定值 的情况, 而 if…else…语句更加灵活,常用于 范围判断
  2. switch 语句仅执行符合条件的代码,效率更高,而if…else 语句所有条件代码都得执行,效率不如前者
  3. 当分支比较少时,if… else 语句的执行效率高
  4. 当分支比较多时,switch 语句的执行效率高,结构更清晰

2.循环流程控制

2.1 for 循环(与计数有关)

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

2.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;
        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);
  • 输出结果:JavaScript 网页编程(一)——JavaScript 基础语法_第2张图片 

2.3 while 循环

  • 使用 while 循环时一定要有 退出条件(完成计数器更新),否则会成为死循环
        var num = 1;        // 计数器 初始化变量
        while (num <= 100) {
            console.log('特特喜欢茶茶');
            num++;          // 操作表达式  完成计数器的更新 防止死循环
        }
        do { // 至少执行一次
            var message = prompt('特特你喜欢我吗?');
            } while (message !== '我喜欢你')
                alert('我也喜欢你ww');

2.4 区分 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 创建数组:var arr = new Array(); 
  • 利用 数组字面量 创建数组(使用最多):var  cute = ['特特','茶茶','桃西西',9999,true];
  • 数组中可以存放任意类型的数据,例如:字符串,数字,布尔值等,如上

3.获取数组中的元素

  • 获取数组中的元素:数组名[索引号],索引号从 0 开始
  • 如果没有和索引号对应的元素,则输出值是 undefined

4.遍历数组(for 循环)

  • 数组的 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长度
  • 修改索引号,追加数组元素,注意不是给数组名直接赋值
        var arr = ['red', 'green', 'blue'];    // 此时数组长度是3
        arr.length = 5;                        // 修改 length长度 新增数组元素 
        console.log(arr);                      // 有五个元素 其中两个因为是空的不显示
        console.log(arr[4]);                   // undefined
        arr1[7] = 'hotpink';                   // 修改索引号 追加数组元素
        arr1[0] = 'yellow';                    // 替换原来的数组元素
        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
            }}
        console.log(newArr);

7.数组元素去重

  • 将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组
  • 思路:声明新数组,遍历旧数组,用 新数组[新数组长度]  追加 符合要求的元素
        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.冒泡排序

  • 原理图解:JavaScript 网页编程(一)——JavaScript 基础语法_第3张图片
        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.函数定义

  • 函数:封装了一段 可被重复调用执行 的代码块
  • 声明函数:function 函数名(形参1,形参2,...){函数体}
  • 调用函数:函数名(实参1,实参2,...);
  • 声明函数 本身并不会执行代码,只有 调用函数 才会执行 代码

2.函数参数

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

3.函数返回值

  • return 终止函数,并返回指定的值,return 后的代码不执行
  • 如果函数没有 return ,返回的值是 undefined
  • return 只能返回最后一个值,如:return num1, num2; // 返回结果是 num2
  • return 如果想返回多个值,可以考虑数组,如: return [num1 + num2, num1 * num2, num1 / num2];
  • 经常用一个变量来接受 函数的返回结果 如:var re = getArrMax([5, 2, 99, 101, 67, 77]);
  • break ,continue ,return 的区别:
  1. break :结束当前的循环体(如 for、while)
  2. continue :跳出本次循环,继续执行下次循环(如 for、while)
  3. return :不仅退出循环,还能够返回 return语句中的值,同时结束当前的函数体内的代码

4.arguments 的使用

  • 只有函数才有 arguments对象,而且是每个函数都内置好了 arguments对象
  • 当不确定有多少个参数传递的时候,可以用 arguments 来获取
  • arguments对象存储了 实参,在函数内部使用
  • arguments 是一个伪数组,可以遍历
  • 关于伪数组:
  1. 具有 length属性
  2. 按索引方式储存数据
  3. 不具有数组的 push() , pop() 等方法
  • 利用函数求任意个数的最大值(不确定输入数,考虑 arguments):
     function getMax() {
            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));                       // arguments中存储了这些实参
        console.log(getMax(1, 2, 3, 4, 5));        

5.函数声明

  • 自定义函数方式 ( 命名函数 ):function fn() {}
  • 自定义函数:函数调用 既可以放到声明函数的前面,也可以放在声明函数的后面
  • 函数表达式 ( 匿名函数):var fn = function(){}; 
  • 匿名函数:函数调用 必须写到 函数体下面;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 预解析

  • 预解析定义:变量和函数 的声明 在代码执行之前执行完成,也叫变量 / 函数提升
  • 变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升
  • 函数提升(函数预解析): 函数的声明会被提升到当前作用域的最上面,但是不会调用函数
         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();                   // 外部函数顺序执行 调用内部函数
  • 集体声明 和 预解析:
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,                  // 多个属性 用逗号隔开
    sayHi : function(){        // 这是匿名函数
        alert('茶茶喜欢特特');
    }};                        // 不要忘记;
  • 区分 变量、属性、函数、方法:
  • 变量 / 函数:单独声明赋值,单独存在,不是对象的一部分
  • 属性 / 方法:对象里面的变量称为属性,不需要声明,是对象的一部分

2.使用 new Object 创建对象

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

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

  • 使用构造函数的原因:减少重复代码
  • 前面两种方法每次只能创建一个对象,构造函数每次可创建多个对象
  • 构造函数中 不需要 return 返回结果
  • 创建对象的时候,必须用 new 来调用构造函数
        function Star(uname, age, sex) {  // 构造函数名字首字母要大写
            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指向,指向创建出来的空对象
  3. 给空对象添加属性和方法
  4. 函数完成之后,返回 this,即创建出来的对象

4.遍历对象(重要)

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 等

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.9)); // 1
        // (2) Math.ceil()   ceil 天花板 向上取整  往最大了取值
        console.log(Math.ceil(1.1)); // 2
        // (3) Math.round()   四舍五入  其他数字都是四舍五入,但是 .5 特殊 它往大了取  
        console.log(Math.round(-1.5)); // 这个结果是 -1 ∵取大的 -1 > -2

3.Date对象(是构造函数)

  • 需要实例化 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);
  • 格式化 年月日:
        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 周日返回的是 0
        var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
        console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
  • 总毫秒数的含义:基于1970年1月1日(世界标准时间)起的毫秒数
  • 获取总毫秒数(时间戳):var now = +new Date();
  • 倒计时效果 (原理:时间戳、时间格式化):
        // 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.Array对象

4.1 检测数组类型

  • instanceof 运算符:检测是否为数组
  • Array.isArray():检测是否为数组,H5 新增的方法
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(Array.isArray(obj));   // false

4.2 添加删除数组元素

  • push(数组后)、unshift(数组前):增加元素,每次添加一个或多个,返回新数组长度
  • pop(数组后)、shift(数组前):删除元素,每次只能删除一个,返回被删除的的元素
        var arr = [1, 2, 3];
        console.log(arr.push(4, 'tea'));           // 1. push() 数组末尾 添加一个或多个数组元素 
        console.log(arr.unshift('red', 'purple')); // 2. unshift() 数组开头 添加一个或多个数组元素
        console.log(arr.pop());                    // 3. pop() 删除数组的最后一个元素 一次只能删除一个
        console.log(arr.shift());                  // 4. shift() 删除数组的第一个元素 一次只能删除一个

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

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

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

4.4 查找指定数组元素

  • indexOf(数组元素):返回该数组元素的索引号,从 前面 开始查找
  • lastIndexOf(数组元素) :返回该数组元素的索引号,从 后面 开始查找
  • 只返回 第一个 满足条件的 索引号,如果找不到 数组元素,则返回的是 -1
  • 数组去重:
        // ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 去除重复元素
        // 核心算法: 遍历旧数组,用旧数组去查询新数组,若该元素在新数组里没出现过,就添加,否则不添加
        // 利用 新数组.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.5 数组转换为字符串

  • 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

5.String对象

5.1 基本包装类型

  • 基本包装类型:把 简单数据类型 包装成为 复杂数据类型,这样 基本数据类型 就有了 属性和方法
  • 比如 String 作为简单数数据类型不应该有 length属性,但实际上它有,因为被 JS 包装了

5.2 字符串的不可变

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

5.3 根据字符返回位置

  • str.indexOf('要查找的字符', [起始的位置]
  • 查找字符串"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 根据位置返回字符(重点)

  • charAt(index):根据位置返回字符,如str.charAt(3)
  • 遍历所有的字符:for (var i = 0; i < str.length; i++) {console.log(str.charAt(i));}
  • charCodeAt(index) :返回字符ASCII值,判断用户按键 
  • 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数:
        // 核心算法:利用 charAt() 遍历这个字符串
        // 1. 遍历对象,得到最大值和该字符
        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();,前面学过 join:把数组转换为字符串
        // 有一个字符串 'abcoefoxyozzopp'  要求把里面所有的 o 替换为 *
        var str1 = 'abcoefoxyozzopp';
        while (str1.indexOf('o') !== -1) {    // 只要里面能查到字符 o
            str1 = str1.replace('o', '*');    // 就把字符 o 替换成 *
        }
        console.log(str1);

        // 2. 字符转换为数组 split('分隔符')
        var str2 = 'red&pink&blue';
        console.log(str2.split('&'));         // 得到数组[red,pink,blue]

 

十四.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.堆栈

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

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. 这个输出什么 ?   狗比特

你可能感兴趣的:(JavaScript)