JSCORE_day02

复习

第三阶段主题: 利用JS来操作浏览器

  • 前提: 学会JS

  • JS的v8引擎提供智能化 自动处理 – 自动修正错误的代码

    • 类型隐式转换: 理论上同数据类型的值才能运算; JS会自动把不同类型转同类型

    • 声明提升: 理论上必须 先声明 再使用 — 正常人书写代码的规范

      • 一旦先使用再声明 也没事: JS引擎会帮你修改代码的顺序, 然后再执行

        在这里插入图片描述

  • 作用域

    • 全局: 浏览器提供的全局对象 是 window, 存放所有系统的api
      • 全局污染: 在脚本中声明的变量会存储在window里, 造成自定义变量 污染全局
    • 局部: 函数运行时 临时 产生的对象, 保存函数中声明的变量
      • 利用局部作用域可以保存私有的属性, 独立于全局之外 – 有效避免冲突
  • 作用域链: 当函数中使用一个变量时, 按照就近原则从最近的作用域中获取

  • 闭包: 对函数/局部作用域 在特殊场景中的称呼

    • 如果一个A函数作用域中的变量 被其他B函数使用, 则这个A作用域会被保存到B函数的scopes属性里, 目的是 防止释放, 导致B函数运行错误

    • 利用闭包: 可以为函数提供私有的 对象属性

      var 函数 = (function(){
          var 变量 =return function (){
              使用 变量...
          }
      })()
      
  • arguments

    • 系统提供的关键词, 用于保存函数收到的所有实参
    • 应用: 函数重载 - 通过判断实参的个数或类型不同, 做不同的逻辑操作
  • this

    • 代表函数运行时所在的对象
    • 应用: 可以把函数放到对象里执行
    • call: 短暂访问 - 把函数临时放到对象中执行, 执行后从对象里立刻删除

对象是引用类型

在这里插入图片描述

构造函数

在这里插入图片描述

原型机制

在这里插入图片描述

call

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>call 短暂访问 09:22</title>
  </head>
  <body>
    <!-- call: 函数的一个属性, 提供了短暂访问对象的功能 -->
    <!-- 把函数放到参数对象里, 运行一次, 再删除 -->
    <!-- 语法:  函数.call(对象) -->
    <script>
      var r1 = { length: 20, width: 30 }

      function area() {
        console.log(this.length * this.width)
      }

      // 复杂方案: 手动
      r1.area = area //先存入对象
      r1.area() // 调用: 函数的this指向所在对象 r1
      delete r1.area //用完清理

      // 函数提供call属性: 自动完成上述任务
      area.call(r1)

      console.log(r1)

      //
      var emp = {
        ename: '亮亮',
        salary: 20000, //薪资
      }

      function total(yue) {
        console.log(this.salary * yue)
      }
      // call(要放入的对象, 实参们...)
      total.call(emp, 12)

      // 计算 n月薪资 + 奖金
      function bonus(yue, bonus) {
        console.log(this.salary * yue + bonus)
      }
      // 计算出: 6个月总薪资 + 40000奖金
      bonus.call(emp, 6, 40000)
    </script>
  </body>
</html>

apply

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>函数的apply 09:44</title>
  </head>
  <body>
    <script>
      // apply的作用 与 call 完全相同
      var r1 = { length: 20, width: 30 }

      function area() {
        console.log(this.length * this.width)
      }

      area.call(r1)
      area.apply(r1)

      // 体积
      function volume(height) {
        console.log(this.length * this.width * height)
      }

      // 计算 高度100 时的体积
      volume.call(r1, 100) //访问对象, 携带实参100
      // 区别:
      // call: 的实参 `散装`的, 要1个1个传递
      // apply: 的实参 `打包/礼盒装`的, 放在数组里一起传
      volume.apply(r1, [100])

      //练习:
      function suibian(x, y) {
        console.log(this.length + this.width + x + y)
      }

      // 分别用 call 和apply 调用, 实参是 200 和 300
      suibian.call(r1, 200, 300)

      suibian.apply(r1, [200, 300])
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>apply 10:16</title>
  </head>
  <body>
    <script>
      // apply的应用场景
      function max() {
        var m = arguments[0]
        for (var i = 0; i < arguments.length; i++) {
          var value = arguments[i]
          if (value > m) m = value
        }

        return m
      }

      var m = max(12, 3, 43, 546, 65)
      console.log(m)

      // 求出此数组的最大值
      var nums = [12, 54, 56, 67, 87, 3]
      // apply: 可以把数组拆包, 作为1个1个参数传递
      // var m = max(nums)
      // 参数1: 代表要放入的对象,作为函数中的this
      // 但是: max函数体中没有使用this关键词, 所以参数1的值随意, 但是必须要写一个值, 来占位
      var m = max.apply(0, nums)
      console.log(m)

      // Math有一个min 求最小值
      var m = Math.min(12, 4, 45, 56, 67, 78, 7)
      console.log(m)
      // 练习: 用min求数组nums里的最小值
      var nums = [12, 54, 56, 67, 87, 3]
      var m = Math.min.apply(1, nums)
      console.log(m)

      // ... :展开符, 把数组的内容展开, 变为1个1个的参数
      var m = Math.min(...nums)
      console.log(m)
    </script>
  </body>
</html>

bind

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>bind 10:44</title>
  </head>
  <body>
    <!-- onclick: 当点击时, 触发 -->
    <button onclick="bind_area()">点我!</button>
    <!-- 另一种语法 -->
    <button onclick="area.call(r1, 20, 30)">点我</button>

    <script>
      // bind: 捆绑 - 把参数和对象 与函数捆绑在一起, 生成一个新的函数
      var r1 = { length: 20, width: 30 }

      function area(x, y) {
        console.log(this.length + this.width + x + y)
      }

      var bind_area = area.bind(r1, 20, 30)
      console.dir(bind_area)
      // BoundThis: 捆绑到函数的对象
      // BoundArgs: 捆绑到函数的实参

      // 特点: 绑定完毕后 但是没有执行
      // 适合延时执行的场景
    </script>
  </body>
</html>

对象引用类型

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>object 11:13</title>
  </head>
  <body>
    <script>
      // 对象类型: 引用传递
      var emp1 = { ename: '泡泡', age: 18 }
      var emp2 = emp1

      emp2.age = 40
      console.log(emp1.age) // 40

      // 基础数据类型: 值传递
      var a = 10
      var b = a
      a = 15
      console.log(b) // 10
    </script>
  </body>
</html>

构造函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>构造函数 11:24</title>
  </head>
  <body>
    <script>
      // 构造函数: 用于 构建创造 对象的函数, 称为构造函数

      // 所有的数据本质都是构造函数创建的, 只是作者为常用的数据设置了语法糖 -- 称为 字面量语法
      var obj = {}
      console.log(obj)

      var x = new Object()
      console.log(x)

      var a = [11, 22, 33]

      var b = new Array(11, 22, 33)

      console.log(a)
      console.log(b)

      function c(x, y) {
        console.log(x + y)
      }
      c(10, 20)

      // 构造语法
      // 最后的形参是函数体, 其他参数是形参名
      var d = new Function('x', 'y', 'console.log(x + y)')
      d(10, 30)
      console.dir(d)

      // 日期
      // 不是所有构造函数都有语法糖, 只有常见的一些作者才提供了
      var e = new Date()
      console.log(e)
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>自定义构造函数 11:37</title>
  </head>
  <body>
    <script>
      // 构造函数相当于是一个工厂, 可以生产产品

      // 制作一个函数Rect, 触发后可以生成 矩形对象
      // 命名规范: 大驼峰命名法 - 首字母大写
      // 从外观: 让程序员可以轻松识别出 是 构造函数
      function Rect(length, width) {
        var x = {} //新建空对象

        x.width = width //存储值 到指定属性名
        x.length = length

        return x //返回组合出来的对象
      }

      // 构造函数: 可以快速创建出 规范的矩形对象
      var r1 = Rect(10, 20)
      console.log('r1:', r1)

      var r2 = Rect(100, 40)
      console.log('r2:', r2)
    </script>
  </body>
</html>

练习

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>练习 11:50</title>
  </head>
  <body>
    <script>
      // 制作一个 Cube 函数, 制作立方体对象
      function Cube(length, width, height) {
        var x = {}

        x.length = length
        x.width = width
        x.height = height

        // 给 x 对象设置共享对象存在哪里
        // __proto__: 固定的关键词, 称为原型链
        x.__proto__ = Cube.prototype

        // 问题: 每个立方体对象 计算面积的函数是相同的
        // 为每个对象配备一个函数, 属于浪费资源
        // 应该: 共用同一个函数即可

        // 计算体积
        // x.volume = function () {
        //   return this.length * this.width * this.height
        // }

        return x
      }

      // 所有函数都有一个prototype属性, 用于存放共享方法
      // prototype: 称为原型
      Cube.prototype.volume = function () {
        return this.width * this.length * this.height
      }

      console.dir(Cube)

      // 使用方式如下:
      var c1 = Cube(10, 20, 30) //长, 宽, 高

      console.log(c1) //{length:10, width:20, height:30}

      console.log(c1.volume())

      var c2 = Cube(5, 10, 3)
      console.log(c2)
      console.log(c2.volume())

      // 技巧: 用360浏览器查看最好
      // 因为360的内核是旧的, 可以看到没有美化前的对象

      console.log(c1.volume == c2.volume)

      // 构造函数不允许生产三无产品
      // 必须为生产的对象, 通过原型链__proto__ 属性, 指定其`售后`由谁负责.  构造函数的prototype 原型属性
      //
      // 原型链机制: 当对象读取一个属性时, 如果本身没有, 则自动到 原型链 链接到的 对象中查找
      console.log(c1.volume())
    </script>
  </body>
</html>

原型

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>原型 14:40</title>
  </head>
  <body>
    <script>
      // 制作 Rect 函数, 制作矩形对象, 要求拥有算面积和周长的方法
      function Rect(length, width) {
        var x = {}

        x.length = length
        x.width = width

        x.__proto__ = Rect.prototype

        return x
      }

      Rect.prototype.area = function () {
        return this.width * this.length
      }
      Rect.prototype.zc = function () {
        return (this.width + this.length) * 2
      }

      // 使用示例:
      var r1 = Rect(20, 50) //长, 宽
      console.log(r1) // {length:20, width:50}

      console.log(r1.area()) //得到1000,  长x宽
      console.log(r1.zc()) //得到周长 140   (长+宽)*2
    </script>
  </body>
</html>

练习

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>练习 15:14</title>
  </head>
  <body>
    <script>
      // 制作一个 圆形 Circle 构造函数
      function Circle(radius) {
        var x = {}
        x.radius = radius

        x.__proto__ = Circle.prototype
        return x
      }

      Circle.prototype.dia = function () {
        return this.radius * 2
      }

      Circle.prototype.area = function () {
        return this.radius * this.radius * 3.14
      }

      Circle.prototype.zc = function () {
        return this.radius * 3.14 * 2
      }

      // 使用方式如下:
      var c1 = Circle(5) //半径
      console.log(c1) // {radius: 5}

      console.log(c1.dia()) // 10   直径=半径*2
      console.log(c1.area()) //      面积 = 3.14*半径*半径
      console.log(c1.zc()) // 周长 = 半径*3.14*2
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>练习 15:30</title>
  </head>
  <body>
    <script>
      // 制作 英雄构造函数 Hero
      function Hero(name, skill_1, skill_2) {
        // new: 此关键词放在函数前, 则会自动完成 3行代码
        // var this = {}

        this.name = name
        this.skill_1 = skill_1
        this.skill_2 = skill_2

        // this.__proto__ = Hero.prototype

        // return this
      }

      Hero.prototype.s1 = function () {
        console.log(this.name + '释放' + this.skill_1)
      }

      Hero.prototype.s2 = function () {
        console.log(this.name + '释放' + this.skill_2)
      }

      //使用示例:
      // new: 此关键词 让构造函数中少写3行
      const h1 = new Hero('孙尚香', '翻滚突袭', '红莲爆弹')

      console.log(h1)
      // {name:"孙尚香", skill_1:'翻滚突袭', skill_2:"红莲爆弹"}

      h1.s1() // 打印出:  孙尚香 释放 翻滚突袭
      h1.s2() // 打印出:  孙尚香 释放 红莲爆弹
    </script>
  </body>
</html>

new

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>new 15:56</title>
  </head>
  <body>
    <script>
      // 用new 配合 构造函数
      function Rect(length, width) {
        this.length = length
        this.width = width
      }

      Rect.prototype.area = function () {
        return this.width * this.length
      }

      // 使用示例
      var r1 = new Rect(20, 40) //长, 宽
      console.log(r1) //{length:20, width:40}

      console.log(r1.area()) //800   面积=长x宽
    </script>
  </body>
</html>

严格模式

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>严格模式 16:21</title>
  </head>
  <body>
    <!-- 严格模式: 在2009年出版的 ES5, 即JS的第五个版本推出的特性 -- 提供更加多的报错, 辅助程序员书写出健康的代码 -->
    <script>
      // 使用严格模式: 书写如下字符串后, 其下方的JS代码将进入严格模式
      // 严格模式下, 变量必须先声明 后使用
      // 有效防止 写错变量名 导致全局污染的情况
      'use strict'

      var servername = 'localhost'

      // 变量前没有前缀, 则默认是 window.
      // alert('111')

      // window.servename = 'www.xin666.vip'

      // 对象.属性名 = 值;  如果属性名不存在会怎么样?? 会新增
      // 导致: 变量名写错, 错误的在全局对象window中新增了此属性
      // -- 全局污染!
      servename = 'www.xin666.vip'

      var obj = { name: '泡泡' }
      obj.naem = '世宇'
      console.log(obj)

      console.log(window) //后台展开查找到上方变量
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>严格模式 16:36</title>
  </head>
  <body>
    <script>
      // 开启严格模式:
      // 在严格模式下, 直接触发全局中的函数, 其this指向undefined
      // 代替之前的window, 避免全局污染
      'use strict'

      function Rect(length, width) {
        // new : 此关键词会改变 this的指向, 指向构造出的对象
        // var this = {}
        console.log('this:', this)
        this.length = length
        this.width = width
      }

      // 要求: 利用Rect制作一个 r1 对象,  长20, 宽50
      // 忘记写new, 函数的this是window, 造成全局污染
      var r1 = Rect(20, 50)
      console.log(r1)

      console.log(window)
      // Rect()
      // window.Rect()
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>严格模式 16:55</title>
  </head>
  <body>
    <script>
      // 严格模式 是2009年出品的 ES5 版本中新增的特性
      // 通过更多的报错, 强制程序员写出健壮的代码
      // 严格模式提供了很多很多功能, 刚才讲解的是 具有代表性的几个特征
      // 推荐以后写JS代码 一定要开严格模式
      // 后续学习的框架中, 都是默认开启严格

      'use strict'
      // 严格模式下提供了更多的报错
      // 取消了 静默失败

      var emp = { ename: '泡泡', age: 18 }
      // freeze: 冻结, 不许动
      Object.freeze(emp)
      // 冻结emp后, 此对象的值无法修改
      emp.age = 40

      console.log(emp)
    </script>
  </body>
</html>

class语法

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>class 17:22</title>
  </head>
  <body>
    <script>
      // 由于JS的 构造函数写法过于复杂;
      // 在2015年6月的 ES6   - JS的第六个版本中
      // 引入了来自java的class语法: 全自动完成原型的操作
      // class: 称为 类
      class Rect {
        // 固定名称的函数 constructor
        // 相当于之前的构造函数, 通过 new 类名()  触发
        constructor(length, width) {
          this.length = length
          this.width = width
        }

        // 所有书写在这个{}中的函数,都会放在原型里
        // 省略function关键词
        area() {
          return this.length * this.width
        }

        zc() {
          return (this.length + this.width) * 2
        }
      }

      console.dir(Rect) //查看 prototype

      var r1 = new Rect(10, 20)
      console.log(r1)

      console.log(r1.area())
      console.log(r1.zc())
    </script>
  </body>
</html>

练习

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>练习 17:39</title>
  </head>
  <body>
    <script>
      // 用class语法制作 Circle 构造函数, 圆形
      class Circle {
        constructor(radius) {
          this.radius = radius
        }

        dia() {
          return this.radius * 2
        }
        zc() {
          return this.radius * 2 * 3.14
        }
        area() {
          return this.radius * this.radius * 3.14
        }
      }

      // 使用示例
      var c1 = new Circle(10) //半径 radius
      console.log(c1.dia()) //直径: 半径x2
      console.log(c1.zc()) //周长: 半径x2*3.14
      console.log(c1.area()) //面积: 半径*半径*3.14
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>练习 17:51</title>
  </head>
  <body>
    <script>
      class Hero {
        constructor(name, skill_1, skill_2, skill_3) {
          this.name = name
          this.skill_1 = skill_1
          this.skill_2 = skill_2
          this.skill_3 = skill_3
        }
        s1() {
          console.log(this.name + '释放' + this.skill_1)
        }
        s2() {
          console.log(this.name + '释放' + this.skill_2)
        }
        s3() {
          console.log(this.name + '释放' + this.skill_3)
        }
      }
      const h1 = new Hero('孙尚香', '翻滚突袭', '红莲爆弹', '究极弩炮')
      h1.s1()
      h1.s2()
      h1.s3()
    </script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>练习</title>
  </head>
  <body>
    <script>
      class Cube {
        constructor(length, width, height) {
          this.length = length
          this.width = width
          this.height = height
        }
        volume() {
          return this.length * this.width * this.height
        }
      }
      var c1 = new Cube(10, 20, 30)
      console.log(c1)
      console.log(c1.volume())
    </script>
  </body>
</html>

总结

  • 函数的this相关事项
    • 函数放在哪个对象中执行, 就代表哪个对象
    • call: 让函数短暂拜访对象 – 临时放到对象里执行, 然后移除
    • apply : 也是临时运行, 实参是打包/礼盒装 放在数组中传递
      • 允许把数组作为参数传递给 需要 1个1个参数的 函数
      • ES6版本中, 使用 ... 代替
    • bind: 把对象和实参捆绑在函数上, 返回一个新的函数
      • 特色: 延时触发, 适合绑定在 元素的事件上, 例如点击事件
  • 构造函数: 用于构造对象类型的函数
    • 原型prototype 存放共享函数
    • __proto__ 原型链, 链接到 prototype
    • new: 简化构造函数的代码
    • class语法: 更加简化构造函数语法
  • 严格模式: 辅助程序员书写更加健康的代码
    • 开启方式: use strict
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值