js基础

155 阅读27分钟

js 的介绍

JS是什么

  • JS是一种运行在客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能
  • 浏览器就是一种运行JS脚本语言的客户端,JS的解释器被称为JS引擎,为浏览器的一部分

JS简史 ==(JS历史,了解为主,感兴趣的可以多看看)==

  • 在WEB日益发展的同时,网页的大小和复杂性不断增加,受制于网速的限制,为完成简单的表单验证而频繁地与服务器交换数据只会加重用户的负担,当时走在技术革新最前沿的 Netscape(网景)公司,决定着手开发一种客户端语言,用来处理这种简单的验证
    • 简单概括:网页的功能越来越多,当时的网速又不行,一些常用的功能用当时的技术处理起来极其复杂,所以 网景 公司需要一个处理这些常用功能对性能影响更低的新语言
  • 1995 年,就职于 Netscape 公司的布兰登·艾奇(Brendan Eich),开始着手为即将于 1996 年 2 月发布的 Netscape Navigator 2 浏览器开发一种名为 LiveScript 的脚本语言。为了尽快完成 LiveScript 的开发,Netscape 与 Sun 公司建立了一个开发联盟。在 Netscape Navigator 2 正式发布前夕,Netscape 为了搭上媒体热炒 Java 的顺风车,临时把 LiveScript 改名为 JavaScript。
    • 简单概括:网景的布兰登·艾奇研发了一个新语言叫做 LiveScript (只用了10天)当时网景和 Sun 公司有合作关系,Sun 公司刚好新推出了一个叫做 Java 的语言很火,网景为了蹭热度就把 LiveScript 改名为了 JavaScript
    • 所以 Java 和 JavaScript 没有关系,完全是两门不同的语言,它们的区别就像:周杰与周杰伦的区别一样
  • 由于 JavaScript 1.0 获得的关注度越来越高,1996 年,微软就在其 Internet Explorer 3 中加入了名为 JScript 的 JavaScript 实现,这意味着有了两个不同的 JavaScript 版本,导致 JavaScript 没有一个标准化的语法和特性。
    • 简单概括:JavaScript 火了后,微软在自家的 IE 浏览器中弄一个和 JavaScript 一样的 JScript,所以就有了两个不同的 JavaScript,导致没有一个标准化的语法和特性了
  • 1997 年,以 JavaScript 1.1 为蓝本的建议被提交给了欧洲计算机制造商协会(ECMA,European Computer Manufacturers Association)。该协会指定 39 号技术委员会(TC39,Technical Committee #39)负责“ 标准化一种通用、跨平台、供应商中立的脚本语言的语法和语义”。TC39 由来自 Netscape、Sun、微软、Borland 及其他关注脚本语言发展的公司的程序员组成,他们经过数月的努力完成了 ECMA-262 标准,定义一种名为 ECMAScript 的新脚本语言。
    • 为了解决上述问题 欧洲计算机制造商协会 ECMA 制定了一个标准,定义了名为 ECMAScript 的新脚本语言,可以把 ECMAScript 是 JS 的一个规范

ECMAScript 发展过程

  • 1998 年 6 月,ECMAScript 2.0 版发布。
  • 1999 年 12 月,ECMAScript 3.0 版发布,成为 JavaScript 的通行标准,得到了广泛支持。
  • 2007 年 10 月,ECMAScript 4.0 版草案发布,对 3.0 版做了大幅升级。草案发布后,由于 4.0 版的目标过于激进,各方对于是否通过这个标准,发生了严重分歧。以 Yahoo、Microsoft、Google 为首的大公司,反对 JavaScript 的大幅升级,主张小幅改动;以 JavaScript 创造者 Brendan Eich 为首的 Mozilla 公司,则坚持当前的草案。
  • 2008 年 7 月,由于各方分歧太大,争论过于激进,ECMA 开会决定,中止 ECMAScript 4.0 的开发,将其中涉及现有功能改善的一小部分,发布为 ECMAScript 3.1,而将其他激进的设想扩大范围,放入以后的版本,由于会议的气氛,该版本的项目代号起名为Harmony(和谐)。会后不久,ECMAScript 3.1 就改名为 ECMAScript 5。
  • 2009 年 12 月,ECMAScript 5.0 版正式发布。Harmony 项目则一分为二,一些较为可行的设想定名为 JavaScript.next 继续开发,后来演变成 ECMAScript 6;一些不是很成熟的设想,则被视为 JavaScript.next.next,在更远的将来再考虑推出。
  • 2011 年 6 月,ECMAscript 5.1 版发布,并且成为ISO国际标准(ISO/IEC 16262:2011)。
  • 2013 年 3 月,ECMAScript 6 草案冻结,不再添加新功能。新的功能设想将被放到 ECMAScript 7。
  • 2013 年 12 月,ECMAScript 6 草案发布。然后是 12 个月的讨论期,听取各方反馈。
  • 2015 年 6 月 17 日,ECMAScript 6 发布正式版本,即ECMAScript 2015。
  • 从 2015 年以后,ECMA 开始每年发布一个小规模增量更新的升级版本,新版本将按照ECMAScript+年份的形式发布,截止目前,已经发布的版本包含 ECMAScript 2016、ECMAScript 2017、ECMAScript 2018、ECMAScript 2019、ECMAScript 2020、ECMAScript 2021、ECMAScript 2022,后续将继续发布新的版本。

JS 的组成

  • JavaScript 是由 ECMAScript,DOM 和 BOM 三者组成的。
    1. ECMAScript: 定义了JavaScript 的语法规范,描述了语言的基本语法和数据类型
    2. DOM (Document Object Model): 文档对象模型
      • 有一套成熟的可以操作 ==页面元素的 API==,通过 DOM 可以操作页面中的元素。比如: 增加个 div,减少个 div,给 div 换个位置等
        • API:
          • application programming interface 的简写;
          • 翻译:应用程序编程接口;大白话:别人写好的代码,或者编译好的程序,提供给你使用,就叫作api
    3. BOM (Browser Object Model): 浏览器对象模型
      • 有一套成熟的可以操作 ==浏览器的 API==,通过 BOM 可以操作浏览器。比如: 弹出框、浏览器跳转、获取分辨率等

js 的三种书写方式

  • 行内式
    <input type="button" value="按钮" onclick="alert('hello world')" />
    
  • 内嵌式
    <body>
        <script>
            alert('hello world')
        </script>
    </body>
    
  • 外链式
    <script src="main.js"></script>
    

js 定义变量

什么是变量?

  • 变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据;
    • 翻译为大白话,我有一个东西需要暂时存储起来,比如说就是一个数字 100,我把它存放到了变量 a 中,我后续想要使用他的时候就可以直接通过变量 a 获取到数字 100
  • 变量其实就相当于一个容器,内部可以存储任意类型的数据,使用变量时,用的是内部存储的数据。

为什么要定义变量?

使用变量可以方便的获取或者修改内存中的数据

如何定义变量

使用一个 var 的关键字进行定义,后面必须加一个空格,空格后面自定义变量名

var a;
var b;
var c;

变量赋值

  • 变量定义之后,初始时没有进行赋值,内部有一个默认存储的值叫 undefined(未定义) 表示内部未赋值,但可以存储数据了
  • 变量赋值的方式:通过等号 = 赋值,等号右边的值赋值给左边的变量 ==(等号在 JS 中叫做 赋值号;书写时,等号 = 两侧习惯书写一个空格)==
// 变量定义
var a;
// 变量赋值
a = 1;
// 变量定义并赋值
var b = 2;

使用变量

直接写变量名即可使用变量;变量在使用前,必须先有定义,如果没有定义,会出现引用错误

课堂案例

  1. 交换变量, 需求: 交换两个变量所保存的值

变量命名规则(必须遵守,不遵守会报错)

  • 由字母、数字、下划线、$符号组成,不能以数字开头
  • 字母区分大小写
  • 不能是关键字和保留字
    • 关键字指的是js中有特殊功能的小词语,比如var、for等
    • 保留字指的是现在没有特殊功能,但是将来新语法中有可能作为关键字使用

变量命名规范(建议遵守的,不遵守不会报错)

  • 变量名必须有意义
  • 遵守驼峰命名法

js 数据类型

JS中的值,无论是字面量还是变量,都有明确的类型

  • 数据类型分类(以基本数据类型为主)
    • Number 数字类型
      • 不区分整数、浮点数、特殊值,都是 Number 类型
    • String 字符串类型
      • 所有的字符串都是 String 类型
    • undefined undefined类型
      • undefined本身就是一个数据,表示未定义,变量只声明不赋值的时候,值默认是 undefined
    • Boolean 布尔类型
      • Boolean 字面量:只有 true 和 false 两个字面量的值,必须是小写字母
      • 计算机内部存储:true 为 1,false 为 0
    • null null类型
      • null 本身就是一个数据
      • 从逻辑角度,null 值表示一个空对象指针
      • 如果定义的变量准备在将来用于保存对象,最好该变量初始化为 null
    • Object 对象类型(后续课程详细讲解)

数据类型检测

  • 为什么要有数据类型检测?
    • JS语言是一门动态类型的语言,变量并没有一个单独的数据类型,而是会随着内部存储数据的变化,数据类型也会发生变化
    • 变量的数据类型,与内部存储数据有关
    • 将来使用变量时,需要知道内部存储的数据是什么类型,避免程序出错
  • 使用 typeof 的方法进行数据检测
    • 检测方式:在 typeof 后面加小括号执行,将要检测的数据放在小括号内部

数据类型转换(转数值 / 转字符串 / 转布尔)

转数值

  1. Number(数据)方法
    • 转型函数Number()可以用于任何数据类型,将其他数据类型转为数字
    • 字符串:纯数字字符串转为对应数字,空字符串和空白字符串转为0,非空非纯数字字符串转为NaN
    • 布尔值:true转为1,false转为0
    • undefined:转为NaN
    • null:转为0
  2. parseInt()方法:字符串转整数方法
    • 对浮点数进行取整操作
      • 对数字取整直接舍弃小数部分,只保留整数
    • 将字符串转为整数数字
      • 将字符串转为整数数字,也包含取整功能
    • 字符串中,必须是纯数字字符串或者数字字符开头的字符串,才能转换为正常数字,且只取整数部分
    • 如果不是数字打头的字符串,会转换为NaN
  3. parseFloat()方法:字符串转浮点数方法
    • 将字符串转为浮点数数字
    • 满足浮点数数字字符必须在字符串开始,如果不在开始返回值都是NaN

转字符串

  1. 变量.toString()方法
  2. String(变量)方法,有些值没有toString(),这个时候可以使用String()。比如undefinednull
  3. + 号拼接字符串方式
    • num + “” ,当 + 两边一个操作符是字符串类型,一个操作符是其他类型的时候,会先把其他类型转换成字符串在进行字符串拼接,返回字符串

转布尔

  1. Boolean(变量)方法
    • 转型函数Boolean()可以用于任何数据类型,将其他数据类型转为布尔类型的值
    • 转为false:NaN、0、“”空字符串、null、undefined
    • 转为true:非0 非NaN数字、非空字符串

js 运算符

  • 什么是运算符?
    • 也叫操作符,是 JS 中发起运算最简单的方式,例如: 5 + 6
    • 表达式的组成包含操作数和操作符,表达式会得到一个结果,然后用结果参与程序

JS 运算符分类

  • 算数运算符( + / - / * / / / % )
    • 运算顺序与数学中的运算顺序一致,先乘除取余,后加减,有小括号先算小括号
  • 赋值运算符( = / += / -= / *= / /= / %= )
  • 比较运算符( > / < / >= / <= / == / === / != / !== )
    • 比较结果只会返回一个布尔类型值,true 或者 false
  • 逻辑运算符( && / || / ! )
  • 自增自减运算符( ++ / -- )
  • 什么是分支语句

  • JS 代码是从上往下按照顺序依次执行的, 从第一行代码一直执行到最后一行
  • 如果有一种情况是我有两段代码, 我只需要执行其中一个即可, 那么就可以用到分支语句
  • 简单来说: 分支语句就是根据我们设定好的条件来决定要不要执行某些代码

if 分支语句

  • if 分支语句的基本书写
    • 语法: if (条件) { 想要执行的代码 }
    if (true) {
        console.log('因为条件是 true 所以 我可以打印出来')
    }
    /**
     * 语法分析:
                if: 关键字,表明后续是一段if分支语句
                (): 小括号内部填写条件, 用于决定是否执行后续内容
                {}: 花括号内部填写要执行的分支代码, 如果条件为真, 则会执行
    */
    
  • if ... else 语句的基本书写
    • 语法: if (条件) { 条件为真时 执行的代码 } else { 条件为假时 执行的代码 }
    if (true) {
        console.log('因为条件是 true 所以 我可以打印出来')
    } else {
        console.log('因为条件是 true 所以 我不会被打印')
    }
    if (false) {
        console.log('因为条件是 false 所以 我不会被打印')
    } else {
        console.log('因为条件是 false 所以 我可以打印出来')
    }
    /**
     * 语法分析:
                if: 关键字,表明后续是一段if分支语句
                (): 小括号内部填写条件, 用于决定是否执行后续内容
                {}: 花括号内部填写要执行的分支代码, 如果条件为真, 则会执行
                else: 表明前边条件都为false时,执行后续的花括号内的代码
    
    */
    
  • if 嵌套语句的基本书写
    • 可以通过 ifelse if 来设置多个条件进行判断
    • 语法: if(条件1){条件1为true时执行} else if (条件2){条件2为true时执行}
    • 会从头开始依次判断条件
      • 如果第一个条件为 true 了, 那么就会执行后面的 {} 的内容
      • 如果第一个条件为 false, 那么就会判断第二个条件
      • 如果第二个条件也为 false, 那么会依次往后执行
    • 注意
      • 多个 {} 只会有一个被执行, 一旦有一个条件为 true 了, 后面的就不再判断了
      • 如果所有的 条件都为 false, 那么会执行最后的 else {} 分支
      • 如果所有的条件都为 false, 且没有最后的 else {} 分支, 那么当前 if 分支不会有任何代码段会被执行
  • 尽可能多的使用案例帮助学员理解和使用

switch 分支语句

  • switch 也是 条件判断语句的一种, 是对于某一个变量的判断(全等的判断,数据类型不一致时会导致判断失败)
    • switch 分支语句的基本书写
    switch (要判断的变量) {
        case 情况1:
            情况1执行的代码
            break;
        case 情况2:
            情况2执行的代码
            break;
        case 情况3:
            情况3执行的代码
            break;
        default:
            上述情况都不满足时执行的代码
    }
    
    • switch 通常是判断某一个变量等于某一个值的时候使用, 比如用户输入一个数字显示今天周几, 输入一个数字显示今天是几月
  • switch 穿透语句的基本书写
    • 从第一个满足条件的 case 开始
    • 如果没有 break, 后面的条件不在判断, 直接执行代码
    • 直到遇到一个 break 或者 switch 结束
    switch (2) {
        case 0:
            console.log('星期日')
        case 1:
            console.log('星期一')
        case 2:
            console.log('星期二')
        case 3:
            console.log('星期三')
        case 4:
            console.log('星期四')
        case 5:
            console.log('星期五')
        case 6:
            console.log('星期六')
        default:
            console.log('请填写一个 0 ~ 6 的数字')
    }
    
  • 尽可能多的使用案例帮助学员理解和使用

三元表达式

  • 三元表达式(三元运算/三目运算/三目)
  • 语法
    • 条件 ? 真-执行的代码 : 假-执行的代码
  • 意义
    • 对 if else 语句的简写
  • 注意
    • 执行代码的位置只能写一句话
  • 常用场景
    • 利用三目执行代码(对if else 的优化)
    • 利用三目给变量赋值
// 执行代码
var num = 5
num % 2 == 0 ? console.log('num 为偶数') : console.log('num 为奇数')

// 给变量赋值
var num = 1 // 我们暂且规定 num == 1 时代表为男性, num == 2 时代表为女性
var gender = num == 1 ? '男' : '女'
console.log(gender)

函数的概念

  • 什么是函数?
    • 首先明确一点,和我们数学中的函数是两个概念
    • 在 JS 中,函数可以理解为将一段在程序中多次出现的代码封装起来的盒子,以便在多个地方调用执行
    • 换句话说:函数就是一个内部封装了部分代码的盒子,可以在多个位置被调用
  • 函数的使用
    • 创建函数(定义函数)
    • 调用函数

函数的定义

  • 声明式定义
function fn() {
    
}
/**
 * 分析:
 *      function:声明函数的关键字,代表接下来这段代码是一个函数
 *      fn:函数名,调用函数时需要使用,函数名自定义,符合命名规范和见名知意即可(!** 匿名函数时可以不写)
 *      ():小括号内存放函数的参数(后续讲解)
 *      {}:存放函数代码,调用函数时,想执行的代码都写在内部
*/
  • 赋值式定义
var fn = function () {

}

函数的调用

function fn1() {
    
}
var fn2 = function () {

}

fn1()
fn2()

声明式与赋值式的区别

  • 书写区别
  • 调用区别
// 声明式
fn1()  // 可以执行
function fn1(){
    // 函数代码。。。。。。
}
fn1()  // 可以执行


fn2()   // 不可以执行(!**  声明时编程,其实就是相当于将一个函数赋值给一个变量,会有变量的声明提升,所以在变量声明前调用时,根据变量声明提升的规则,此时变量为 undefined ,所以不能被调用)
var fn2 = function () {
    // 函数代码。。。。。。。。。
}
fn2()   // 可以执行

函数的参数

  • 参数是什么?
    • 如果没有参数,那么函数的执行功能是固定的,写好函数后内部内容将不会变
    • 比如:函数内部的代码为 1 + 1,那么始终执行时始终都是 1 + 1,如果此时想要计算 1 + 2 的值,需要重新封装一个 1+2 的函数
  • 参数在哪里?如何使用
    • 书写函数时有一个 () 内部就是书写参数的,函数分为两种,形参---实参
  • 形参和实参的区别
    • 形参:在函数声明时 function 后边的()内书写,每写一个参数,就相当于在函数内部创建一个变量,其值为函数调用时传递的值,只能在函数内部使用,不能在外部使用
    • 实参:顾名思义,实际的参数,也就是函数在调用时传递的参数
function num () {
    console.log(1 + 1)
}
num()   // 打印值为 1+1

function num (a, b) {   // 此处 a b 为形参
    console.log(a + b)
}
num(1, 1)   // 此处为 实参,分别传递给 a  和  b
num(1, 2)   // 此处打印值为 1 + 2
  • 注意
    • 函数的形参与实参是按照从左到右的顺序一一对应的
// 少传参数
function num1(a, b, c, d) {
    console.log(a,b,c,d)
}
num1(1, 2, 3, 4)    // 打印1,2,3,4
num1(1, 2, 4) // 打印1,2,4,undefined
num1(4) // 打印4,undefined,undefined,undefined
// 多传参数
function num2 (a) {
    console.log(a)
}
num2(1, 2)  // 打印 1
num2(1)  // 打印 1

函数的返回值

  • 返回值是什么?有什么作用
    • 函数内部默认有一个 return 他的值就是函数的返回值,如果函数内部不写 return 那么函数默认在函数体内部最底部返回一个 undefined
    • 如果不想返回 undefined 需要手动在函数内部写上 return 并且跟上需要返回的值
    • 可以中断函数(后续通过代码演示)
function num (a, b) {
    a+b
}
var ab = num(1,2)
console.log(ab)
function num (a, b) {
    // return a + b
    console.log('函数内部执行的 a + b =',a+b)
}
var ab = num(1,2)
console.log('函数外部执行的 a + b =',ab)

函数的优点

  • 函数其实就是将一段需要多次调用的代码抽离出来封装到一个盒子内部,方便在多个地方调用时简单化代码
    • 抽离公共代码,项目代码整体更加简洁
    • 方便(复用),在需要的地方直接 函数名 + 小括号 调用即可

函数的预解析

  • 什么是预解析
    • 在代码运行前,先全部分析一遍代码,这个行为叫做预解析(预解释)
  • 预解析的内容
    • 声明式函数定义
    • var 声明变量
// 正常书写代码
fn()
console.log(a)

function fn() {
    console.log(100)
}
var a = 100

// 预解析后可以理解为
function fn() {
    console.log(100)
}
var a

fn()
console.log(a)

a = 100

作用域

  • 什么是作用域?
    • 简答一句话概述:变量生效的范围
    • 变量不是在所有地方都是可以使用的,而这个变量的可使用范围 就是作用域

全局作用域 && 局部作用域

  • 全局作用域
    • 最大的作用域
    • 在全局作用域中定义的变量可以在任何地方使用
    • 页面打开时浏览器给我们生成了一个全局作用域 window 这个作用域一直存在,直到浏览器页面关闭时才会销毁
    • var num = 100; var num2 = 200 这两行代码的变量就是存储在全局作用域下面,可以在任意地方去使用
  • 局部作用域
    • 局部作用域就是在全局作用域内的某一个地方,相对比较小的一些作用域
    • 在局部作用域中定义的变量只能在当前的这个作用域内部使用,在全局作用域或者其他的局部作用域中不可以使用
    • 在 JS 中,只有函数能生成一个局部作用域,别的都不行
    • 简单来说,每一个函数内部都是一个局部作用域
    var num = 100 // 全局作用域下声明的变量,在任何地方都可以使用
    
    function fn() {
        var num2 = 200  // 在当前位置声明的变量都是 fn 函数局部作用域内的变量, 也就是说只能在当前 fn 函数内部使用
    }
    

作用域链

  • 作用域链是一个纯概念性的东西
  • 当我们在某一个作用域内获取某一个变量时
  • 会先在当前作用域查找,找到直接拿来用,没找到会向上层查找
  • 如果上层作用域也没找到,那么会继续向上层作用域的上层作用域查找,一直到查找到全局作用域
  • 这样一层一层向上查找构成一个链条(假设有,不是真的有链条),我们叫做作用域链
var num = 100;

function fn() {
    var num2 = 200

    function fun() {
        var num3 = 300

        console.log(num3)   // 自己当前作用域就有(fun函数内部),拿过来直接用
        console.log(num2)   // 自己当前作用域没有(fun函数内部),去上一层查找,发现有(fn函数内部),拿过来用
        console.log(num)    // 自己当前作用域没有(fun函数内部),去上一层查找,发现没有(fn函数内部),继续向上一层作用域查找,发现有(全局作用域),直接用
        console.log(a)  // 自己没有,一级一级向上查找,到全局作用域还是没有,报错
    }
}

变量使用规则

访问规则

  • 变量的访问规则 也叫做 作用域的查找机制
    • 作用域的查找机制只能向上查找,不能向下查找
function fn() {
    var num = 100
}
fn()

console.log(num)    // 全局作用域没有,相当于已经查找到顶层,所以报错找不到,不会向 fn的局部作用域查找

赋值规则

  • 当我们想要给某一个变量赋值的时候,就要先找到这个变量,然后再给它赋值
  • 赋值规则
    • 先在自己作用域内部查找,有就直接赋值
    • 没有就去上一级作用域内部查找,有就直接赋值,如果没有继续向上一级作用域内部查找
    • 如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,再给他赋值
function fn() {
    num = 100
}
fn()

/**
 * fn 调用以后,要给 num 赋值
 * 查找自己作用域没有后,向上层查找
 * 上层就是全局作用域,发现还是没有
 * 那么会把 num 定义为全局的变量,并给它赋值
 * 所以 fn 函数调用后,全局就有了一个变量叫做 num 并且值是 100
*/

递归函数

  • 什么是递归?
    • 在编程世界中,递归就是一个自己调用自己的手段
    • 递归函数:在一个函数内部,调用了自己,循环往复
/**
 * 这就是一段简单的递归,在函数内部调用了自己,函数一执行,就调用自己一次,在调用在执行,循环往复没有尽头
*/
function fn() {
    fn()
}
fn()
  • 其实递归函数和循环很类似
    • 需要有初始化,自增,执行代码,条件判断
    • 如果没有就会是一个没有尽头的递归函数,我们通常叫这种为 死递归

写一个简单的递归

/**
 * 求 1 至 5 的和
 * 
 *  1 + 2 = 3
 *  3 + 3 = 6
 *  6 + 4 = 10
 *  10 + 5 = 15
*/

// 写递归的第一步,先写结束条件(为了避免出现死递归)
function add (n) {
    if (n == 5) {
        return 5
    }
}
add(1)

// 第二步,写不满足结束条件时的递归操作
function add (n) {
    if (n == 5) {
        return 5
    } else {
        return n + add(n + 1)
    }
}
add(1)

简单了解对象

  • 什么是对象
    • 首先排除男女朋友, 我们这是正经编程
    • 对象是一个 复杂数据类型, 也叫做 引用数据类型
    • 虽然我们说是复杂类型, 但是也没有很复杂, 只不过是存储了一些基本数据类型的集合
var obj = {
    num: 100,
    str: 'hello',
    boo: true
}
  • 这里的 {} 和函数中的 {} 不一样, 函数内部书写代码, 对象里面是书写数据的
  • 对象就是一个键值对的集合
    • 什么是键值对?
      • 对象 obj 中, num 是键, 100 是值
      • 对象 obj 中, str 是键, 'hello' 是值
      • 对象 obj 中, boo 是键, true 是值
    • 其实就是我们准备一个房子, 把我们想要的数据放进去, 然后把房子的地址给到变量名, 当我们需要某一个数据的时候, 就可以根据变量名里面存储的地址找到对应的房子, 然后去房子里面找到对应的数据

创建对象* 字面量方式创建对象

* 语法:`var obj = {}   var obj1 = {键值对, 键值对}`
  • 内置构造函数创建
    • 语法:var obj = new Object()
  • 对象内对于 键(key) 的要求
    • 推荐使用符合变量命名规则和规范的名字
    • 可以使用纯数字当作 键名
      • 这种情况下该属性会排列在最前面
    • 可以使用任何特殊符号
      • 使用特殊符号的时候,在书写时需要被引号包裹

对象数据类型的操作(增删改查)两种语法

  • 点语法
    var obj = {}
    obj.name = 'qianfeng'   // 增
    obj.name = 'qianfeng123'    // 改
    console.log(obj.name)       // 查
    delete obj.name         // 删
    
  • 中括号语法(数组语法)
    var obj = {}
    obj['name'] = 'qianfeng'        // 增
    obj['name'] = 'qianfeng123123'  // 改
    console.log(obj['name'])        // 查
    delete obj['name']              // 删
    
  • 两者的差异
    • 符合变量命名规范与规则的情况,两者并无差异
    • 操作不符合变量命名规范与规则的名称时,比如纯数字或者带有特殊符号的,就只能用中括号语法
    • 涉及变量相关的时候,只能使用中括号语法

for in 循环遍历对象

for (var k in obj) {
    console.log('我执行了', k, obj[k])
}

数据类型赋值的区别

  • 基本数据类型:赋值以后,两个变量没有关系了
  • 复杂数据类型:赋值以后,两个变量操作一个存储空间
  • 两种数据类型存储的区别
    • 基础数据类型直接存储在 栈内存中
    • 复杂数据类型会将数据本体存在堆内存中,变量名存储在堆内存中,变量名内部存储着指向堆内存的地址

数组数据类型

创建数组数据类型

数组的 length 属性

数组的 索引 概念

for 循环遍历数组

不同数据类型的存储(堆和栈)

循环语句

  • 什么是循环语句
    • 根据某些给出的条件,重复执行同一段代码
  • 循环必须要有某些固定的内容组成
    • 初始化
    • 条件判断
    • 要执行的代码
    • 自身改变

while 循环语句

  • while,中文叫 当…时,其实就是当条件满足时就执行代码,一旦不满足了就不执行了
  • 语法 while (条件) { 满足条件就会执行 }
  • 因为满足条件就执行, 所以我们写的时候一定要注意, 就是设定一个边界值, 不然就一直循环下去了, 简称: 死循环, 电脑卡死的时间根据电脑性能有所不同, 建议不要尝试
// 1. 初始化条件
var num = 0
// 条件判断
while (num < 10) {
    // 3. 要执行的代码
    console.log('当前 num 的值是: ', num)
    // 4. 自身改变
    num += 1    // 如果没有这行代码, 那么自身就没有改变, 条件将会一直满足, 代码也就会一直执行
}

do...while 循环语句

  • 是一个和 while 循环类似的循环
  • while 会先进行条件判断, 满足就执行, 不满足就直接不执行了
  • do...while 的循环是 先不管条件, 先执行一次, 然后再开始进行条件判断
  • 语法: do { 要执行的代码 } while (条件)
// 1. 初始化
var num = 10;
do {
    // 3. 要执行的代码
    console.log('我执行了一次')
    // 4. 自身改变
    num += 1
// 2. 条件判断
} while (num < 10)

for 循环语句

  • 和 while do while 循环都不太一样的一种循环结构
  • 但道理是和其他两种一样的, 都是循环执行代码的
  • 语法: for (var i = 0; i < 10; i++) { 要执行的代码 }
// 把初始化, 条件判断, 自身改变, 都统一写在了一起
for (var i = 1; i <= 10; i++) {
    console.log(i)  // 会打印 1~10
}
// 初次使用时会觉得有一点繁琐与不习惯, 但是用起来比较好用

流程控制语句

  • break 关键字的应用
    • 在循环没有进行完毕的时候, 因为我设置的条件满足了, 就直接提前终止循环
    • 举个例子: 我要吃五个包子, 我吃了三个了, 这时候吃饱了吃不下去了, 我就停止了继续吃包子这件事
    • 那么此时要停止循环, 就可以直接使用 break 关键字
for (var i = 1; i <= 5; i++) {
    // 每循环一次,就吃一个包子
    console.log('我吃了一个包子')
    // 当 i == 3 的时候, 条件为 true, 执行了 {} 里面的代码终止循环, 循环就不会继续向下执行了, 也就没有 4 和 5 了
    if (i == 3) {
        break
    }
}
  • continue 关键字的应用
    • 在循环中, 把循环的本次跳过去, 继续执行后续的循环
    • 举个例子: 还是吃五个包子, 要吃第三个的时候, 第三个掉地上了, 所以就不吃第三个了, 继续吃第四个和第五个
    • 跳过本次循环, 就可以使用 continue 关键字
for (var i = 1; i <= 5; i++) {
    // 当 i == 3 的时候, 执行 {} 里面的代码
    // {} 里面有 continue, 那么本次循环后面的代码就都不执行了
    // 自动算作 i 为 3 的这一次结束了, 去继续执行 i == 4 的那次循环
    if (i == 3) {
        console.log('这是第三个包子, 掉地下了, 我不吃了')
        continue
    }
    console.log('我吃了一个包子')
}

循环嵌套的书写

  • 循环嵌套其实就是一个循环内部又写了一个循环
for (var i = 0; i < 3; i++) {   // 这个循环称为 外层循环
    for (var k = 1; k < 4; k++) {   // 这个循环称为 内层循环
        /**
         * 重点!!!
         *          两个循环的循环变量不能相同, 会有冲突
        */
    }
}