ES6 class-数值扩展-方法扩展

目录

class 类

ES6 声明类

class 类静态成员

ES5 构造函数继承

ES6 类继承

子类对父类方法的重写

class 中 getter 和 setter 设置

数值扩展

Number.EPSILON

二进制和八进制

Number.isFinite

Number.isNaN

Number.parseInt

Number.parseFloat

Number.isInteger 

Math.trunc

Math.sign

对象方法扩展

Object.is

Object.assign

Object.setPrototypeof

Object.getPrototypeof


class 类

ES6 提供了更接近传统语言的写法,引入了 Class(类)的概念,作为对象的模板

通过 class 关键字,可以定义类

基本上,ES6 的 class 可以看作是一个语法糖,它的绝大部分功能,ES5都可以实现

新的 class 写法只是让对象圆形的写法更加清晰、更像面向对象编程的语法而已

知识点:

  • class 声明类
  • constructor 定义构造函数初始化
  • extends 继承父类
  • super 调用父级构造方法
  • static 定义静态方法和属性
  • 父类方法可以重写

ES6 声明类

// 手机
// ES5 声明 class 方法
function Phone(brand, price) {
  this.brand = brand
  this.price = price
}

// 添加方法
Phone.prototype.call = function () {
  console.log('打电话')
}

// 实例化对象
let Huawei = new Phone('华为', 5999)
// 调用方法
Huawei.call() // 打电话
console.log(Huawei) // Phone {brand: "华为", price: 5999}

// ES6 声明方法
class Phone1 {
  // 构造方法 constructor
  // 该方法在类执行 new+类名时,就会自动执行实例对象的 constructor 方法
  constructor(brand, price) {
    // 添加属性
    this.brand = brand
    this.price = price
  }

  // 添加方法,方法必须使用该语法,不能使用 ES5 的对象完整形式
  call() {
    console.log('听音乐')
  }
}
let hongmi = new Phone1('红米k40', 2499)
console.log(hongmi) // Phone1 {brand: "红米k40", price: 2499}

class 类静态成员

  • 添加属性或方法要添加到原型上(prototype),实例对象是通过原型链去找属性或方法的
  • 函数的静态成员只属于函数对象本身(类),不属于实例对象
  • 函数对象和实例对象的属性和方法不是相通的
  • 实例对象和构造函数原型的属性和方法是相通的
// ES5 构造函数
function Phone() {}
// Phone.name 和 Phone.price 只属于函数对象(类),并不属于实例对象
// 对于这样的属性,我们称之为静态成员
Phone.myname = 'vivo'
Phone.price = function () {
  console.log('vivoZ10 仅售2499')
}

// 实例对象
let vivo = new Phone()
console.log(vivo.myname) // undefined,实例对象并没有构造函数对象上的属性
console.log(Phone.myname) // vivo,意味着实例对象和函数对象的属性是不通的

// vivo.price(); // 方法也没有,提示 price 并不是一个函数

// 实例对象与构造函数原型对象是相通的
// 构造函数原型对象
Phone.prototype.myname = 'vivoX10'
Phone.prototype.mysize = '5.5inch'
let vivo1 = new Phone()
console.log(vivo1.myname) // vivoX10
console.log(vivo1.mysize) // 5.5inch
console.log(Phone.mysize) // undefined

// ES6 构造函数
class shouji {
  // static 静态成员
  static myname = '苹果'
  static functions() {
    console.log('打电话,听音乐')
  }
}
let iPhone = new shouji()
console.log(iPhone.myname) // undefined
console.log(shouji.myname) // 苹果
// 再次证明,static 标注的属性和方法属于类,但不属于实例对象

ES5 构造函数继承

// 手机
function Phone(brand, price) {
  this.brand = brand
  this.price = price
}

Phone.prototype.functions = function () {
  console.log('打电话,听音乐')
}

// 以上是父级构造函数
// 声明一个子级构造函数
// 智能手机
function SmartPhone(brand, price, color, size) {
  // 调用父级构造函数初始化代码,两个 this
  Phone.call(this, brand, price) // Phone 通过 call 方法改变 this 值
  // 此处的 this 指向 SmartPhone 里面的 this ,即 SmartPhone 中的一个实例对象
  // 继承父级构造函数的 brand 和 price 属性
  this.color = color
  this.size = size
}

// 设置子级构造函数的原型
SmartPhone.prototype = new Phone() // 如此,子级的实例对象就会有父级的属性和方法
SmartPhone.prototype.constructor = SmartPhone // 校正,可有可无

// 声明子类的方法
SmartPhone.prototype.photo = function () {
  console.log('拍照')
}
SmartPhone.prototype.game = function () {
  console.log('玩游戏')
}

// 实例化
const chuizi = new SmartPhone('锤子', 2499, '黑色', '5.5inch')
console.log(chuizi) 
// SmartPhone {brand: "锤子", price: 2499, color: "黑色", size: "5.5inch"}

ES6 类继承

class Phone {
  // 构造方法
  constructor(brand, price) {
    this.brand = brand
    this.price = price
  }

  // 父类的成员属性
  functions() {
    console.log('打电话')
  }
}

// 声明子类
class SmartPhone extends Phone {
  // 构造方法,里面包含子类中实例化值的初始化参数
  constructor(brand, price, color, size) {
    // 调用父类的构造方法初始化
    super(brand, price) // 功能与 Phone.call(this, brand, price) 相同
    this.color = color
    this.size = size
  }
  photo() {
    console.log('拍照')
  }
  game() {
    console.log('玩游戏')
  }
}

// 实例化
const xiaomi = new SmartPhone('小米', 2499, '黑色', '5.5inch')
console.log(xiaomi) 
// SmartPhone {brand: "小米", price: 2499, color: "黑色", size: "5.5inch"}
xiaomi.functions() // 打电话
xiaomi.photo() // 拍照
xiaomi.game() // 玩游戏

子类对父类方法的重写

class Phone {
  // 父类的成员属性
  functions() {
    console.log('打电话')
  }
}

// 声明子类
class SmartPhone extends Phone {
  // 重写 functions 方法
  functions() {
    // 注意,在 JS 中,子类不能直接调用父类的同名方法
    // 此处也不可以使用 super()
    // super() 是父类构造方法,只在创建对象时使用
    // 通过 super() 方法调用 call() 方法
    // 因此只能重写父类方法
    console.log('视频/语音通话')
  }
}

// 实例化
xiaomi.functions() // 视频/语音通话

class 中 getter 和 setter 设置

  • 对对象的属性进行方法的绑定
  • 对某一个属性进行获取,执行 get 函数
  • 封装对象的动态属性,属性值随着数据的变化而变化,动态获取数据
  • 对某一个属性进行设置,执行 set 函数
  • 添加更多的控制和判断,成功赋值,失败跳过

数值扩展

Number.EPSILON

  • Number.EPSILON 是 JavaScript 表示的最小精度
  • EPSILON 属性的直接接近于 2.22*10^(-16)
  • 如果两个数的差值小于 Number.EPSILON,就认为两个数相等
  • 主要用于浮点数运算中的精度设置
// Number.EPSILON
function equal(a, b) {
  if (Math.abs(a - b) < Number.EPSILON) {
    return true
  } else {
    return false
  }
}
console.log(0.1 + 0.2 === 0.3) // false
console.log(equal(0.1 + 0.2, 0.3)) // true

二进制和八进制

  • 二进制表示方式:0b
  • 八进制表示方式:0o
  • 十进制
  • 十六进制:0x
// 二进制
let two = 0b1010
console.log(two)
// 八进制
let eight = 0o777
console.log(eight)
// 十进制
let ten = 100
console.log(ten)
// 十六进制
let sixteen = 0xff
console.log(sixteen)

Number.isFinite

  • 检测一个数值是否为有限数
// Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100)) // true
console.log(Number.isFinite(100 / 3)) // true
console.log(Number.isFinite(100 / 0)) // true
console.log(Number.isFinite(Infinity)) // true

Number.isNaN

  • 检测一个数值是否为 NaN
// Number.isNaN 检测一个数值是否严格等于 NaN
console.log(Number.isNaN(100)) // false
console.log(Number.isNaN('100')) // false
console.log(Number.isNaN('str')) // false

Number.parseInt

Number.parseFloat

  • 字符串转为数值型
  • 一个字符串中包含数字时,如果字符串的首位为数字,则输出该数字及与该数字相连的数字,且之后的内容截断不输出
  • 如果字符串首位不为数字,则输出 NaN
// Number.parseInt Number.parseFloat 字符串转为整型
console.log(Number.parseInt('521zdn')) // 521
console.log(Number.parseInt('zdn521')) // NaN
console.log(Number.parseFloat('5.21zdn')) // 5.21
console.log(Number.parseFloat('zdn5.21')) // NaN

Number.isInteger 

  • 判断一个数是否为整数
// Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(100)) // true
console.log(Number.isInteger(100.1)) // false
console.log(Number.isInteger('100')) // false
console.log(Number.isInteger('hello')) // false

Math.trunc

  • 将数字的小数部分抹掉
// Math.trunc 将数字小数部分抹掉
console.log(Math.trunc(5.21)) // 5
console.log(Math.trunc('5.21')) // 5
console.log(Math.trunc('5.21 hello')) // NaN
console.log(Math.trunc('hello')) // NaN

Math.sign

  • 判断一个数到底为正数、负数、还是零
// Math.sign 判断一个数到底为正数、负数、零
console.log(Math.sign(10)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-99)) // -1

对象方法扩展

Object.is

  • 判断两个值是否完全相等
  • 与全等很像,但并不完全相同
  • 在判断 NaN 与 NaN 是否全等的时候,结果并不一致
// Object.is 判断两个值是否完全相等
// 与全等很像但并不是完全相同
console.log(Object.is(120, 120)) // true
console.log(Object.is(NaN, NaN)) // true
console.log(Object.is('hello', 'hello')) // true
console.log(Object.is('hello', 'world')) // false
// NaN 不等于 任何数值
console.log(120 === 120) // true
console.log(NaN === NaN) // false
console.log('hello' === 'hello') // true
console.log('hello' === 'world') // false

Object.assign

  • 对象的合并
  • 经常用于配置的合并
  • 合并的两个对象,后者将覆盖前者重名的属性,不重名的属性将被保留
// Object.assign 对象的合并
// 经常用于配置的合并
// 合并的两个对象,后者会覆盖前者重名的属性,不重名的属性将会被保留
const config1 = {
  host: 'localhost',
  port: 3306,
  name: 'root',
  password: 'root',
  test: 'test',
}

const config2 = {
  host: 'http://www.jnshu.com/',
  port: 3307,
  name: 'IT 修真院',
  password: 'root',
}

// 括号中的两个参数,第一个为被覆盖对象,第二个为覆盖对象
const config = Object.assign(config1, config2)
console.log(config) // 输出结果为 config2
// {host: "http://www.jnshu.com/", port: 3307, name: "IT 修真院", password: "root", test: "test"}

Object.setPrototypeof

Object.getPrototypeof

  • 设置原型对象与获取原型对象
  • 虽然此方法可以改变对象的原型,但并不建议这样做
  • 正确的做法还是通过 Object.creat 创建对象时就设置好原型,效率更高
// Object.setPrototypeOf 设置原型对象
const school = {
  name: 'imau',
}
const campus = {
  xiaoqu: ['西区', '东区', '南区', '新区'],
}

// 为 school 设置原型 Object.getPrototypeOf 获取原型
// 将第二个参数插入第一个参数中作为原型
Object.setPrototypeOf(school, campus)
console.log(Object.getPrototypeOf(school)) // {xiaoqu: Array(4)}
// 获取到的是 school 的原型 campus
console.log(school) // {name: "imau"}
// 虽然可以通过这样的方式改变对象的原型,但是并不建议这样做
// 正确的做法还是通过 Object.create 创建对象时就将原型设置好
// 效率更高

你可能感兴趣的:(es6,javascript,前端)