27.了解ES5.1

上一章:css预处理器

1. 了解ES5.1

  • 文档:https://www.w3cschool.cn/kesyi/kesyi-nqej24rv.html
  • ECMAScript其实是指一种规范,或者说是一个标准。具体点来说,它其实就是一份文档(ECMA-262
  • ES5的最后版本是ES5.1, 在ES5.1中提出了一些新的特性
    • Strict Mode(严格模式)
    • JSON对象
    • Object扩展
    • Array扩展
    • Function.prototype.bind

2. 严格模式(了解)

理解

  • 文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode
  • 默认使用非严格模式/常规模式(sloppy mode),ES5.1添加了第二种运行模式:“严格模式”(strict mode)
  • 顾名思义,这种模式使得Javascript在更严格的语法条件下运行

作用

  • 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷
  • 消除代码运行的一些不安全之处,为代码的安全运行保驾护航
  • 为未来新版本的JavaScript做好铺垫

开启严格模式

  • 写法一: 在全局第一行指定为: ‘use strict’, ==> 所有代码都以严格模式运行
  • 写法二: 在函数体的第一行指定为: ‘use strict’ ==> 仅当前函数以严格模式运行。
  • 如果浏览器不支持, 只解析为一条简单的语句, 没有任何副作用

有哪些变化?

编码非严格模式严格模式
给未声明的变量赋值自动创建全局变量报错(未定义)
函数中的this可以指向window不能指向window, 而是undefined
同名形参允许不允许
/* 
ES5默认是非严格模式
开启严格模式: 'use strict'
严格模式的变化:
  | 编码               | 非严格模式       | 严格模式                      |
  | 给未声明的变量赋值 | 自动创建全局变量 | 报错(未定义)                  |
  | 函数中的this       | 可以指向window   | 不能指向window, 而是undefined |
  | 同名形参      | 允许             | 不允许                        |
  
*/

'use strict' 

/* | 给未声明的变量赋值 | 自动创建全局变量 | 报错(未定义)   | */
// a = 2
// function fn() {
//   b = 3
// }
// fn()
// console.log(a, b)

/* | 函数中的this       | 可以指向window   | 不能指向window, 而是undefined | */
// function fn() {
//   console.log(this)
// }
// fn()

/* | 同名形参      | 允许             | 不允许                        | */
// function fn(a, a) {
//   console.log(a)
// }
// fn(1, 2)

// delete Object.prototype

面试题

  • 说出几个严格模式的语法特性变化

3. JSON与JSON对象(重要)

JSON

  • https://baike.baidu.com/item/JSON/2462549?fr=aladdin

  • JSON全称 JavaScript Object Notation,是一种轻量级的通用的数据交换格式, 专门用来存储结构化的文本数据

    • json对象: {key1: value1, key2: value2}
    • json数组: [value1, value2]
    • key只能是string
    • value可以是: string / number / boolean / null / {} / []
    • 特别注意: json中的string只能用双引号, 不能用单引号
  • 应用JSON的场景?

    • 存储JSON数据的文件 ==> JSON文件 ==> xxx.json
    • 前后台交互传输文本数据 ==> JSON文本(也就是json字符串)
  • JSON 与 JS 对象的关系

    • JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串
  • 以前存储或传输结构化的数据都是用XML格式, 现在更多的是用json格式

    • json更小

    • 解析和生成更快

      /*
      需求: 存储2个人的信息: 
      	jack/18岁/喜欢football&basketball&pingpang
      	tom/21岁/喜欢pingpang
      */
      
      data.xml
      <students>
          <student>
          	<name>tom</name>
              <age>18</age>
              <likes>
                  <like>football</like>
                  <like>basketball</like>
                  <like>pingpang</like>
              </likes>
          </student>
          <student>
          	<name>jack</name>
              <age>21</age>
              <likes>
                  <like>pingpang</like>
              </likes>
          </student>
      </students>
      
      data.json
      [
        {
          "name": "tom",
          "age": 18,
          "likes": ["football", "basketball", "pingpang"]
        },
        {
          "name": "jack",
          "age": 21,
          "likes": ["pingpang"]
        }
      ]
      
      /*返回json数据的在线接口: https://dog.ceo/api/breeds/image/random */
      
      // js对象
      var obj = {
          name: 'tom',
          age: 18,
          likes:['football', 'basketball', 'pingpang']
      }
      
      // js数组
      var arr = [
          {
              name: 'tom',
              age: 18,
              likes:['football', 'basketball', 'pingpang']
          },
          {
              name: 'jack',
              age: 21,
              likes:['pingpang']
          }
      ]
      

JSON对象

  • 用途: 专门用来做 json 字符串与 js 对象/数组之间的相互转换的内置对象
  • 语法
    • JSON.stringify(obj/arr)
      • js对象/数组 ==> 转换为json字符串
    • JSON.parse(json)
      • json字符串 ==> 转换为js对象/数组

        /* 
        JSON对象
        */
        /* 1. 将js对象/数组转换为json字符串: JSON.stringify() */
        const personJson = JSON.stringify(person)
        console.log(personJson)
        
        /* 2. 将json字符串解析为js对象/数组: JSON.parse() */
        const person2 = JSON.parse(personJson)
        console.log(person2)
        

面试题

  • 说说你对JSON的理解
  • 比较一下 JSON 与 XML
  • 利用 JSON 对象实现对象深拷贝

4. Object扩展

存取器属性 (次重要)

  • get propertyName(){} 用来得到当前属性值的回调函数 ==> getter

  • set propertyName(value){} 用来监视当前属性值变化的回调函数 ==> setter

    /* 
    需求: 一个人有姓 / 名 / 姓名 3个属性, 要求:
          1. 姓名组成: 姓-名
          2. 改变姓或者名, 姓名也会对应改变
          3. 改变姓名, 姓和名也会对应改变
    */
    
    const p = {
      firstName: 'A',
      lastName: 'B',
      // fullName: 'A-B' // 不能实现需求2与3
      /* getter在读取属性值时自动调用, 返回值作为属性值, this是当前对象 */
      get fullName () {
        console.log('fullName getter')
        return this.firstName + '-' + this.lastName
      },
    
      /* setter在设置新的属性值时自动调用, 用来监视属性值的变化, this是当前对象 */
      set fullName (value) {
        console.log('fullName setter', value)
        const names = value.split('-')
        this.firstName = names[0]
        this.lastName = names[1]
      }
    }
    
    console.log(p.fullName)
    
    p.firstName = 'C'
    p.lastName = 'D'
    console.log(p.fullName) // 导致对应的getter调用返回属性值
    
    p.fullName = 'E-F' // 导致对应的setter调用 ==> 根据需求去更新firstName与lastName
    console.log(p.firstName, p.lastName)
    

Object.defineProperty() (重要)

  • 文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

  • 功能: 为对象添加新属性,或者修改已有属性

  • 语法: Object.defineProperty(obj, prop, descriptor)

    • obj为目标对象
    • prop为属性名
    • descriptor为属性描述符 ==> 描述属性相关信息的配置对象
      • get: 属性的 getter 函数

      • set: 属性的 setter 函数

      • value: 属性的初始值

      • writable: 标识属性值是否可修改的布尔值

      • enumerable: 标识是否可以被枚举遍历的布尔值

      • configurable: 标识是否可以重新定义的布尔值

        /* 
        需求: 给一个人(有姓/名) 添加姓名属性, 要求:
              1. 姓名组成: 姓-名
              2. 改变姓或者名, 姓名也会对应改变
              3. 改变姓名, 姓和名也会对应改变
        */
        'use strict'
        const p = {
          firstName: 'A',
          lastName: 'B'
        }
        Object.defineProperty(p, 'fullName', {
          /* getter在读取属性值时自动调用, 返回值作为属性值, this是当前对象 */
          get: function () {
            console.log('fullName getter')
            return this.firstName + '-' + this.lastName
          },
          
          /* setter在设置新的属性值时自动调用, 用来监视属性值的变化, this是当前对象 */
          set: function (value) {
            console.log('fullName setter', value)
            const names = value.split('-')
            this.firstName = names[0]
            this.lastName = names[1]
          },
        
          enumerable: true, // 可以枚举遍历
        })
        
        console.log(p.fullName)
        
        p.firstName = 'C'
        p.lastName = 'D'
        console.log(p.fullName) // 导致对应的getter调用返回属性值
        
        p.fullName = 'E-F' // 导致对应的setter调用 ==> 根据需求去更新firstName与lastName
        console.log(p.firstName, p.lastName)
        
        Object.defineProperty(p, 'foo', {
          value: 'abc', // 指定初始值
          writable: false, // 是否可修改
          configurable: false, // 是否可以重新定义
          enumerable: false, // 是否可枚举遍历
        })
        
        console.log(p.foo)
        
        // p.foo = 'cba'  // 不能修改只读属性
        // console.log(p.foo)
        
        // Object.defineProperty(p, 'foo', {   // 不能重新定义
        //   configurable: true
        // })
        
        // keys()得到指定对象自身可枚举的属性名的数组  ==> 没有foo属性
        Object.keys(p).forEach(key => {
          console.log(key, p[key])
        })
        

Object.defineProperties() (了解)

  • 功能: 与defineProperty类似, 但可以一次定义多个属性
  • 语法: Object.defineProperties(obj, descriptors)
    • obj: 目标对象

    • descriptors:包含一个或多个属性描述符的对象

      /* 
        Object.defineProperties()   (了解)
        功能与defineProperty类似, 但可以一次定义多个属性
      */
      var obj = {
        name: 'foo'
      }
      Object.defineProperties(obj, {
        color: {
          value: "yellow",
          enumerable: true
        },
        length: {
          value: "10m",
        }
      })
      console.log(obj)
      

Object.create() (次重要)

  • 功能: 用于创建指定对象的子对象, 并可以扩展新的属性

  • 语法: Object.create (prototype, descriptors)

    • prototype: 指定隐式原型对象(也就是父对象)

    • descriptors: 包含一个或多个属性描述符的对象

      /* 
      Object.create()    (次重要)
        - 功能: 用于创建指定对象的子对象, 并可以扩展新的属性
        - 语法:  Object.create (prototype, descriptors)
          - prototype:  指定隐式原型对象(也就是父对象)
          - descriptors: 包含一个或多个属性描述符的对象
      */
      const obj1 = {
        name1: 'abc'
      }
      
      // 创建一个obj1的子对象, 不扩展新属性
      const obj2 = Object.create(obj1)
      console.log(obj2, obj2.name1) // obj2的原型对象为obj1, 也就是obj2是obj1的子对象
      
      // 创建一个obj1的子对象, 扩展新属性
      const obj3 = Object.create(obj1, {
        name2: {
          value: 'aaa',
          enumerable: true
        },
        name3: {
          value: 'bbb'
        }
      })
      console.log('obj3', obj3)
      
      //创建一个干净的对象: 没有自己的属性也没有原型对象
      const obj4 = Object.create(null)
      console.log('obj4', obj4)
      

面试题

  • 给对象定义属性的多种方式
  • 说说属性的getter与setter函数
  • 如何创建一个对象的子对象

5. 数组的扩展(非常重要)

API

  • Array.prototype.forEach(function(item, index){}) : 遍历数组

  • Array.prototype.indexOf(value) : 得到值在数组中的第一个下标

  • Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标

  • Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组

  • Array.prototype.filter(function(item, index){}) : 遍历过滤出一个新的子数组

  • Array.prototype.some(function(item, index){}): 判断是否有一个元素满足条件

  • Array.prototype.every(function(item, index){}): 判断是否所有元素都满足条件

  • Array.prototype.reduce(function(preTotal, item, index){}) : 遍历返回一个累加的结果

练习

// 1. 输出arr中所有的值和对应的下标
// 2. 得到arr中第一个3的下标和最后一个3的下标
// 3. 判断arr中有没有奇数的元素
// 4. 判断arr中是否全部元素都是奇数
// 5. 得到一个由arr中值大于5的元素组成的数组
// 6. 得到一个比arr中每个元素都大10的数组
// 7. 得到arr中所有奇数的和
// 8. 得到arr中所有奇数加10后组成的数组
const arr = [6, 3, 5, 7, 3, 8]

// 1. 输出arr中所有的值及对应的下标
arr.forEach((item, index) => {
  console.log(item, index)
})

// 2. 得到arr中第一个3的下标和最后一个3的下标
console.log(arr.indexOf(3), arr.lastIndexOf(3))

// 3. 判断arr中有没有奇数的元素
console.log(arr.some(function (item) {
  return item%2===1
}))

// 4. 判断arr中是否全部元素都是奇数
console.log(arr.every(function (item) {
  return item%2===1
}))

// 5. 得到一个由arr中值大于5的元素组成的数组
console.log(arr.filter(function (item) {
  return item>5
}))

// 6. 得到一个比arr中每个元素都大10的数组
console.log(arr.map(function (item) {
  return item + 10
}))

// 7. 得到arr中所有奇数的和
console.log(arr.reduce(function (preTotal, item) {
  return preTotal + (item%2===1 ? item : 0)
}, 0))

// 8. 得到arr中所有奇数加10后组成的数组
console.log(arr.reduce(function (pre, item) {
  if (item%2===1) {
    pre.push(item + 10)
  }
  return pre
}, []))

面试题

  • 说出几个开发中常用的数组方法

    push,indexof,filter,reduce,find,some,every
    
  • 对数组[6, 3, 5, 7, 3, 8]进行去重处理

    var arr = [6,3,5,7,3,8];
    
    
  • 对多维数组进行扁平化处理

    // 扁平化操作==》多维数组变一维数组
    var arr = [1,[2,[4,2{}]]]
    

6. 函数的扩展(重要)

API

  • Function.prototype.bind(thisArg, arg1, arg2, …)

  • Function.prototype.call(thisArg, arg1, arg2, …)

  • Function.prototype.apply(thisArg, [argsArray])

面试题

  • 区别call与bind
  • 自定义call与bind

7. Error

理解

  • 文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error

  • JS引擎在解析执行JS代码时发现存在错误时,会自动抛出特定类型包含特定message的error对象

  • 当我们判断出程序运行不满足我们的需求时, 可以手动抛出error对象

  • Error有3个常见的子类型

    • ReferenceError: 引用了不存在的变量
    • TypeError:类型不对
    • SyntaxError: 语法错误
  • 一旦抛出了错误, 我们如果没有捕获处理,程序就会中断运行

  • 错误处理

    • 抛出错误: throw new Error(‘错误信息’)
    • 捕获错误:try { 可能出错的代码 } catch (error) {}
  • 注意:throw抛出的可以是任意类型值, 而不仅仅是error对象

编码测试

/* 
Error有3个常见的子类型
  - ReferenceError: 引用了不存在的变量
  - TypeError:类型不对
  - SyntaxError: 语法错误
*/

/* 演示常见的内置错误 */

// console.log(a) // Uncaught ReferenceError: a is not defined
// console.log('-----') // 不会执行  一旦抛出了错误, 我们如果没有捕获处理,程序就会中断运行

// var a = {}
// a() // Uncaught TypeError: a is not a function

// var a = "你的外号叫 "土豆""  // Uncaught SyntaxError: Unexpected identifier

/* 手动抛出错误 */
function fn(day) {

  if (day<1 || day>31) {
    throw new Error('日号必须在1到31之间')
  }
  console.log('今天是' + day + '号')
}

// 捕获错误
try {
  fn(21)
  fn(-1)
} catch (e) {
  alert(e.message)
}
console.log('catch之后的处理')

try {
  throw 2  // throw本质上可以抛出任意类型值
} catch (e) {
  console.log('e', e)
}

面试题

  • 说出3种常见的错误
  • 说出错误的2种处理

了解完ES5.1,下一章,让我们快速进入ES6+的学习

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值