预解析、作用域、变量的三个机制、对象、数组

一、预解析

1.预解析概念

  + 不是教给你怎么写代码
  + 告诉你代码的执行机制, 和不要怎么写代码
  + 预: 预先, 在所有代码执行之前
  + 解析: 解释, 对代码进行通读并解释(只是把整体代码当作一个文档)

2.解释了什么东西

+var 关键字
	=>会把var关键字定义的变量在代码块执行之前声明
+ 声明式函数
	=>会把这个函数名在所有代码块执行之前声明,并且赋值为一个函数
注意:赋值式函数
	=>var fn = function () {}
	=>按照 var 的规则进行解析

3.扩展

报错信息

    + Uncaught TypeError: fn is not a function
    + 当你看到它的时候
      => 我前面的代码是不是用过 fn 这个变量了

4.预解析的无节操

(1). 不管 if 条件是不是成立,里面的代码都会进行预解析
(2). return 后面的代码虽然不执行,但是会进行预解析

二、作用域

1.作用域的定义

作用域

    + 教给你怎么写代码
    + 作用: 生效, 有用
    + 域: 范围
    + 作用域: 变量(变量名, 函数名)生效的范围

2.分类(2种)及上下级关系

  1. 全局作用域

    + 打开的一个页面就是一个全局作用域
    +  全局作用域,叫做 window
    
  2. 私有作用域 (局部作用域)

    + 只有函数生成私有作用域
    + 每一个函数就是一个私有作用域
    
  3. 作用域的上下级关系
    你的函数写在哪个作用域下,你就是谁的子级作用域

  • 作用域的上下级关系有什么用

     + 为了确定变量的范围
     + 三个机制
     +   1.变量定义机制
     +       + 有 var 关键字    var num
     +       + 声明式函数       function fun() {}
     +   2.变量使用机制
     +       + 需要拿到某一个变量来使用
     + 		 + n++
     +   3.变量赋值机制
     + 		 + 一定要有赋值符号   num = 100
    
function fn() {
      // 这个位置就是 fn 私有作用域

      function a() {
        // 这个位置式 fn 私有作用域下的 a 私有作用域
      }

    }

    function fun() {
      // 这个位置就是 fun 私有作用域
    }

    var f = function () {
      // 这个位置就是 f 私有作用域
    }

3.作用域里面的预解析

  • 作用域里面的预解析

      + 预解析分成几个阶段
        1. 全局预解析
        2. 私有作用域预解析
      + 全局预解析
        => 会在页面打开的时候就进行了
        => 只解释属于全局的内容
      + 私有作用域的预解析
        => 当函数执行的时候
        => 进行预解析
        => 函数内部的预解析, 只属于函数内部
    
  • 问题:

      + 函数执行的时候, 会进行形参赋值
      + 函数执行的时候, 会进行预解析
      + 一旦函数的形参和定义的私有变量重名
        => 先预解析还是先形参赋值
      + 结论:
        => 因为函数是单独进行预解析
        => 在函数执行的时候, 先进行形参赋值, 在进行预解析
    

三、变量的三个机制

  • 变量的定义机制

    + 一个变量(函数)
    + 定义在哪一个作用域里面
    + 只能在当前作用域, 或者下级作用域里面使用
    + 上一级作用域不能使用
    
  • 变量使用机制

      + 当你需要使用一个变量(函数)
      + 会首先在自己作用域内查找, 如果有, 直接使用
      + 如果没有, 取上一级作用域查找, 如果有, 直接使用
      + 如果还没有, 再去上一级查找
      + 直到 window 都没有, 那么就 **报错**
    
  • 变量赋值机制

     + 当你需要给一个变量(函数名)赋值的时候
     + 会首先在自己作用域内查找, 如果有, 直接赋值
     + 如果没有, 取上一级作用域查找, 有就赋值
     + 还没有, 再去上一级作用域查找, 有就赋值
     + 直到 window 都没有, **把这个变量定义为全局变量, 在进行赋值**
    

四、对象

1.对象数据类型

  • (1). 对象数据类型

      + JS 数据类型的一种
      + 一个复杂数据类型 Object
      + 函数: 一个盒子, 承载一段代码
      + 对象: 一个盒子, 承载一堆数据
      + 本质: 抽象的描述一个事物
    
  • (2).对象的创建方式

      1. 字面量创建
        => var o = {}
      2. 内置构造函数创建
        => JS 给我们提供了一个内置构造函数叫做 Object
        => var o = new Object()
    
1. 字面量创建对象
     var o = {}
     console.log(o)
2. 内置构造函数创建对象
     var o2 = new Object()
     console.log(o2)
3. 字面量创建直接添加成员
     =>表示我的对象里面有两个成员
     =>一个是 num 成员, 他的值是 100
     =>一个是 str 成员, 他的值是 'hello world'
     =>管他们叫做对象的属性
     =>一个是 fn 成员, 他的值是一个 函数
     =>管他们叫做对象的方法
     var o = {
       num: 100,
       str: 'hello world',
       fn: function () { console.log('我是 o 的 fn 函数') }
     }

     console.log(o)
  • (3).两种创建方式的区别

      1. 字面量创建可以在创建的时候就向直接添加一些数据
        => 数据是以键值对的形式出现
        => key: value 的形式
        => key 就是这个数据的名字
        => value 就是这个数据的值
        => 多个数据之间使用 逗号(,) 分隔
      2. 内置构造函数目前我们不好直接添加成员
        => 直接创建一个空对象
        => 后期通过对象的操作语法来进行增删改查
    

2.对象的操作语法及区别

  • 对象的操作语法

      + 增: 向对象里面添加一个成员
      + 删: 删除对象里面的一个成员
      + 改: 修改对象里面的一个成员
      + 查: 获取对象里面某一个成员的值
      + 怎么创建的对象无所谓, 就是操作对象的
    
  • 语法有两种

      1. 点语法
        1-1. 添加一个成员
          => 语法: 对象名.成员名 = 值
        1-2. 删除一个成员
          => 语法: delete 对象名.成员名
        1-3. 修改一个成员
          => 语法: 对象名.成员名 = 值
          => 原先有就是修改, 原先没有就是添加
        1-4. 查询某一个成员的值
          => 语法: 对象名.成员名
          => 当你访问一个对象里面没有的成员的时候
          => 会给你一个 undefined
      2. 数组关联语法
        1-1. 添加一个成员
          => 语法: 对象名['成员名'] = 值
        1-2. 删除一个成员
          => 语法: delete 对象名['成员名']
        1-3. 修改一个成员
          => 语法: 对象名['成员名'] = 值
          => 原先有就是修改, 原先没有就是添加
        1-4. 获取一个成员的值
          => 语法: 对象名['成员名']
    
  • 注意:

     + 因为对象数据类型是一个复杂数据类型
     + 在控制台打印的时候, 会出现两种情况
     + 现在的样子和最终的样子
       => 在控制台上, 你不展开对象数据类型的时候, 是当前的样子
       => 在控制台上, 你展开对象数据类型以后, 就是最终的样子
     + 解决问题
       1. 你直接打印你想看到的值
       2. console.table()  (在控制台以表格的形式打印)
    
点语法
 0. 创建一个对象
     var o = {}
     console.table( o)

 1. 点语法操作对象
     1-1. 添加一个成员
     向对象里面添加了一个叫做 name 的成员, 值是 'Jack'
     o.name = 'Jack'
     o.age = 18
     console.table( o)

 1-2. 删除一个成员
     删除对象中的 name 成员
     delete o.name
     console.table( o)

 1-3. 修改一个成员
     把 o 对象内的 age 成员修改成 20
     o.age = 20

 1-4. 访问对象内的某一个成员
     我要拿到 o 对象内的 age 成员存储的值, 打印出来
     console.log(o.age)
     console.table( o)


 数组关联语法
    var o = new Object()

1. 操作对象
  1-1. 添加一个成员
    o['name'] = 'Jack'
    o['age'] = 18

  1-2. 删除一个成员
    delete o['name']

  1-3. 修改一个成员
    o['age'] = 20

  1-4. 获取一个成员的值
    console.log(o['age'])
    console.log(o)
  • 对象两种操作语法的区别

      + 点语法
        => 不能使用变量
        => 不能拼接字符串
        => 点的后面是什么, 这个成员名称就是什么
      + 数组关联语法
        => 可以使用变量
        => 可以拼接字符串
    
var obj = {}

    var name = 'abc'

    // 添加一个叫做 name 的成员
    // 就是在添加一个叫做 name 的成员, 和 name 变量没有任何关系
    obj.name = 'Jack'

    // 添加一个叫做 age 的成员
    obj['age'] = 18

    // 当你中括号里面书写一个变量的时候
    // 会把变量的值当作这个成员名称
    // 因为 name 变量的值是 'abc'
    // 下面代码等价于 obj['abe']
    obj[name] = 'hello world'


     for (var i = 1; i <= 100; i++) {
       obj['o' + i] = i
     }
     console.log(obj)



    // 同样是一个变量使用
    // 你是要使用 age 的值, 来当作 obj 的一个成员名称
     obj[age] = 20
     console.log(obj)

3.循环遍历对象

  • 循环遍历对象

      + 遍历过 arguments
        => 因为 arguments 的排序是一组有规律的数字
        => for 循环能给我们提供一组有规律的数字
        => arguments 的索引(下标) 可以访问到里面的某一个成员
      + 遍历 对象
        => 成员名可以访问当对象里面的每一个数据
        => 所有的名字不一定存在规律
      + 我们有一个叫做 fon in 的循环
        => 大部分时候用来遍历对象的
        => 语法:
          for (var 变量 in 对象) {
            重复执行的代码
          }
          -> 根据对象内有多少个成员执行多少回
          -> 循环的每一次, key 分别是对象的成员名称(字符串类型)
          -> 就可以利用 key 和 数组关联语法 来获取每一个成员的值
    
   var obj = {
       name: 'jack',
       age: 18,
       gender: '男',
       score: 100
     }
// for in 遍历对象
     for (var key in obj) {
       console.log('我执行了')
       console.log(key)
       // 当 key === 'name' 的时候, 就是 obj['name']
       // 当 key === 'age' 的时候, 就是 obj['age']
       console.log(obj[key])
     }
     /*
      判断一个成员是不是在这个对象里面
        + 使用 in 语法
        + 成员名 in 对象名(以字符串的形式书写)
        + 对象内的每一个成员名称都必须是字符串
        + 返回的是一个布尔值
          -> 有就是 true
          -> 没有就是 false
    */
     var obj = {
       name: 'jack',
       age: 18,
       gender: '男',
       score: 100
     }
     console.log('name', in obj)   //true
    
  • 扩展

      + window 的 name 属性
        => 是一个全局天生自带的属性
        => 作用: 在 iframe 标签和 name 属性合作进行跨域的
        => 特点: 被固定为字符串类型了
          -> 不管你给 name 赋值为什么数据类型
          -> 他都会自动转换成 字符串 
    

4.数据类型存储的区别、赋值上的区别

  • 数据类型存储的区别

      + 数据类型分成两种
        => 基本数据类型
          1. Number 数值
          2. String 字符串
          3. Boolean 布尔
          4. Undefined 空
          5. Null 空
        => 复杂数据类型
          1. Function 函数
          2. Object 对象
      + 存储上是有区别的
      + JS 打开的内存空间
        => JS 是一个脚本语言, 依赖于浏览器执行
        => 本质是依赖浏览器里面的 JS 解析引擎
        => JS 本身不打开内存空间
        => 因为浏览器在你的电脑上运行的时候, 会占用一段内存空间
        => JS 就是在这一段内存空间里面运行的
        => 数据类型的存储, 就是存储在浏览器分配给 JS 存储的一段空间
      + 浏览器的一段存储空间
        1. 栈内存
          => 存储机制, 先来进栈底
        2. 堆内存
          => 存储机制, 随机存储
      + 数据类型的存储
        1. 基本数据类型
          => 直接把值存储在栈内存里面
        2. 复杂数据类型(地址数据类型 / 引用数据类型)
          => 把数据放在了堆内存里面
          => 把地址放在栈内存的变量里面
          => 我们管这个地址叫做引用
      + 代码的执行
        => 我们只能直接访问当栈里面的内容
        => 你要想访问某一个对象里面的成员
        => 因为对象本身在堆内存里面
        => 我们就需要利用栈里面的地址, 找到堆里面的空间
        => 然后取访问内部的成员
    
var num = 100
    var str = 'hello'

    var obj = {
      name: 'Jack',
      age: 18
    }

    console.log(obj.name)
    console.log(obj.age)
    console.log(age)

  • 数据类型赋值的区别

      1. 基本数据类型
        => 就是把变量存储的值直接赋值给另一个变量
        => 赋值过后两个变量没有关系了
      2. 复杂数据类型
        => 因为复杂数据类型中, 变量存储的是地址
        => 赋值的时候, 实际上是把一个变量的地址给了另一个变量
        => 赋值过后, 两个变量操作一个空间
      3. 函数的形参和实参的关系
        => 实参就是在函数调用的时候给形参赋值
        => 实参和形参的交互, 和变量赋值时一个道理
      4. 函数的返回值也是变量赋值的一种
        => 返回值是吧函数内部的数据 return 出去
        => 在函数外面有一个变量接收
    

5.函数也是一个对象

  • 函数也是一个对象

      + 函数是保存一段代码
      + 对象是保存一段数据
      + 函数本身也是一个对象, 可以保存一堆数据
      + 函数的存储空间
    
  • 函数

      + 当你定义号一个函数以后
      + 函数就有两个功能
        1. 函数名()
          => 把函数当作一个函数来执行掉
        2. 函数名.成员名 = '值'
          => 存储一些数据
      + 这两个功能互相不干扰
        => 也没有关系
    

五、数组

1.数组数据类型

  • 数组数据类型

      + 也是 JS 的一种数据类型
      + 也是复杂数据类型 Array
      + 一个盒子: 存储一堆数据
        => 不是按照键值对存储
        => 按照索引进行存储的(序号)
    
  • 数组的创建

      1. 字面量创建
        => var arr = []
      2. 内置构造函数创建
        => JS 给我们提供了一个内置构造函数 Array
        => var arr = new Array()
    
  • 创建的时候直接添加一些成员

      1. 字面量
        => 直接写在中括号里面, 多个数据使用 逗号(,) 分隔
      2. 内置构造函数
        2-1. 不传递参数
          => 创建一个空数组
        2-2. 传递一个正整数
          => 这个参数表示数组的长度
        2-3. 传递多个数据
          => 每一个数据都是放在数组里面的数据
          => 没有表示长度的数据了
    
  1. 字面量创建
     var arr = []
     console.log(arr)

     2. 内置构造函数创建
     var arr = new Array()
     console.log(arr)

     3. 字面量创建直接添加数据
     var arr = ['hello', 'world', '你好', '世界']
     console.log(arr)

     4. 内置构造函数直接添加数据
     4-1. 不传递参数
     var arr = new Array()
     console.log(arr)

     4-2. 传递一个数字
     var arr = new Array(100)
     console.log(arr)

     4-3. 传递多个数据
    var arr = new Array(10, 20, 30)
    console.log(arr)

2.数组的操作

  • 数组有一个 length 属性

       => 是一个读写的属性
         -> 读: 获取数组的长度
         -> 写: 设置数组的长度
           => 当你设置的比本身长度小, 那么就相当于删除
           => 当你设置的比本身长度大, 那么多出来的就是用空补齐
    
  • 数组的排列

        => 按照索引进行排列的
        => 索引:
          -> 从 0 开始, 依次 +1
          -> 最后一位的索引, 就是 length - 1
        => 索引也是一个读写的属性
          => 读: 读取到指定索引位置的数据
            -> 如果数组确实有这个索引位置, 那么就是这个位置的数据
            -> 如果数组没有这个索引位置, 那么就是 undefined
          => 写: 设置指定索引位置的数据
            -> 如果有这个索引位置, 那么就是给这个索引位置设置
            -> 如果没有这个索引位置, 那么就是添加
            -> 如果这个数字超出 length 很多, 那么中间的位置用空补齐
    
  • 数组的遍历

       => 因为数组是按照索引进行排列的
       => for 循环能给我们提供一组有规律的数字
       => 使用 for 循环遍历一个数组
    
for (var i = 0; i < arr.length; i++) {
       console.log(arr[i])
     }
  • 数组也是一个对象

        => 数组除了可以按照索引排列一些数组
        => 还可以当作对象使用, 使用 点语法 存储一些数据
        => 你把数组当作对象使用的时候, 他的成员是不占用 length 位置的
        => 当你把数组当作对象使用 for in 循环来遍历的时候
          -> 里面的每一个索引位置, 每一个 key 都会遍历出来
        => 一般不会那他当作对象使用
    
// 数组当作对象
    // 当一个数组创建号以后, 他这个名字就可以当作对象使用存储数据
    arr.age = 18
    arr['gender'] = '男'

    // age 和 gender 成员不影响循环遍历数组
     for (var i = 0; i < arr.length; i++) {
       console.log(arr[i])
     }
// for in 循环
    // 是只要有一个 成员名称 在这个 arr 里面就执行一会
    for (var key in arr) {
      console.log(arr[key])
    }


    console.log(arr)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值