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 Class 方法 Override 示例及语法 在 ES6 中,可以通过继承机制实现类方法的重写(override)。子类通过 `extends` 关键字继承父类,并可以重新定义父类中的方法。以下是详细的说明和示例: #### 继承与方法重写的语法 当一个子类继承自父类时,它可以提供自己版本的方法来替代父类中相同名称的方法。这种行为称为 **方法重写** 或者 **Override**。 ```javascript class Parent { greet() { return "Hello from Parent"; } } class Child extends Parent { greet() { return "Hello from Child"; // 子类重写了父类的greet方法[^1] } } const parentInstance = new Parent(); console.log(parentInstance.greet()); // 输出: Hello from Parent const childInstance = new Child(); console.log(childInstance.greet()); // 输出: Hello from Child ``` 上述代码展示了如何通过继承实现方法重写。子类 `Child` 定义了自己的 `greet()` 方法,这会覆盖掉父类 `Parent` 的同名方法--- #### 调用被重写的方法 (`super`) 如果需要在子类中调用父类已被重写的方法,可以使用 `super` 关键字。 ```javascript class Parent { greet(name) { return `Hello ${name} from Parent`; } } class Child extends Parent { greet(name) { return `${super.greet(name)} and also from Child`; // 使用 super 调用父类方法[^2] } } const childInstance = new Child(); console.log(childInstance.greet("Alice")); // 输出: Hello Alice from Parent and also from Child ``` 在这个例子中,子类不仅实现了自己的逻辑,还保留了父类的功能并通过 `super` 进行扩展--- #### 块级作用域与方法重写的关系 需要注意的是,在方法内部声明变量时应考虑块级作用域的影响。例如,使用 `let` 和 `const` 可以创建局部变量而不会污染外部环境[^3]。 ```javascript class Parent { showScope() { let message = "This is Parent's scope"; return message; } } class Child extends Parent { showScope() { const message = "This is Child's scope"; // 局部变量message仅限于此函数的作用域内 return message; } } ``` 此片段强调了即使是在方法重写过程中,也需注意遵循现代 JavaScript 的最佳实践,比如利用块级作用域减少潜在冲突。 --- #### 导入/导出模块化的类结构 为了使项目更加模块化,通常将不同的类分别放置到独立文件中并相互引用。假设有一个名为 `parent.js` 文件以及另一个叫作 `child.js` 文件,则可按如下方式操作: ##### parent.js ```javascript export default class Parent { methodToOverride() { return "Original Method in Parent"; } } ``` ##### child.js ```javascript import Parent from './parent'; export default class Child extends Parent { methodToOverride() { return "Overridden Method in Child"; // 重写来自Parent的方法[^4] } } ``` 这样做的好处在于提高了代码复用性和维护性的同时保持清晰度。 --- #### 替代传统互换算法的方式 虽然题目并未提及具体需求,但值得注意的一点是关于两个数值交换的传统做法可以用更简洁的形式完成——即借助数组解构赋值特性简化过程[^5]: ```javascript let a = 5, b = 10; // 利用ES6 解构赋值快速交换两数 [a, b] = [b, a]; console.log(`a=${a}, b=${b}`); // 结果分别为10和5 ``` 这种方法相较于经典三步运算符形式显得更为直观优雅。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值