ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JS类的创建和继承总结(含ES6 class类)

2022-05-05 13:35:19  阅读:151  来源: 互联网

标签:function ES6 prototype Star name 继承 sex JS class


1. 类的创建

1.1 ES5中类的创建 (即构造函数的创建)

// 注:ES5中类的创建其实就是构造函数的创建,和函数创建相同,只是函数名首字母一般推荐大写
// 1. 方法一:直接在构造函数中直接定义属性和方法
//    优点:可以传参
//    缺点:每 new 一个实例,就会复制一份构造函数里面的属性和方法,费内存
function Star(name, sex) {
  this.name = name
  this.sex = sex
  this.role = '明星'
  this.singSong = function () {
    console.log('他唱的歌叫' + song)
  }
}
// 2. 方法二:先创建一个构造函数(类),然后在原型上挂载属性和方法
//    优点:继承公共属性或方法的时候不费内存,因为它相当于引用,也就是指向的问题,并非“复制”
//    缺点:定义非公共属性时费内存,而且不高效,即不能够用传参来“定制”属性值
function Star() {}
Star.prototype.name = '刘德华'
Star.prototype.sex = '男'
Star.prototype.role = '明星'
Star.prototype.singSong = function (song) {
  console.log('他唱的歌叫' + song)
}
// 3. 总结及注意:
//    3.1 一般将私有属性(即属性值不同的)定义在构造函数(类)中,公共的方法定义在原型上
//    3.2 当构造函数中的属性或方法和原型上的相同时,构造函数内的优先级高

// 4. 举例:
//    4.1 在构造函数中定义“私有”属性
function Star(name, sex) {
  this.name = name
  this, (sex = sex)
}
//     4.1 在原型上定义公共属性或方法
//    写法1:
Star.prototype.role = '明星'
Star.prototype.singSong = function (song) {
  console.log('他唱的歌叫' + song)
}
//    写法2:
Star.prototype = {
  role: '明星',
  singSong: function (song) {
    console.log('他唱的歌叫' + song)
  }
}

1.2 ES6中类的创建和继承

// 创建类
class Star {
  // 构造方法,固定写法
  constructor(name, sex) {
    this.name = name
    this.sex = sex
    this.role = '明星'
  }
  // 公共方法
  getName(name) {
    console.log('他的名字是' + name)
  }
}

// 子类继承
class LiuDeHua extends Star {
  constructor(name, sex, role) {
    super(name, sex) // super 表示继承父类的属性
    this.role = role // 表示子类自己添加的
  }
  sing(song) {
    // 子类自己的方法
    console.log('我唱了' + song)
  }
}

// 下面测试
let ldh = new LiuDeHua('刘德华', '男', '四大天王')
console.log(ldh.name) // 刘德华
ldh.getName('liudehua') // 他的名字是liudehua
ldh.sing('忘情水') // 我唱了忘情水

 

2. ES5中类的继承

2.1 基于原型链继承

// 1. 定义好的类
function Star(name, sex) {
  this.name = name
  this.sex = sex
}
Star.prototype.role = '明星'
Star.prototype.singSong = function (song) {
  console.log('他唱的歌叫' + song)
}

// --------------------------------------------------------

// 2. 用原型链的方式实现继承
//   2.1 创建一个空的函数(子函数)
function LiuDeHua() {}
//   2.2 让子函数的原型指向构造函数,相当于在原型上 new 一个构造函数
//       让子函数的原型上拥有构造函数的全部属性和方法
LiuDeHua.prototype = new Star('刘德华', '男')
//   2.3 new 一个实例,然后调用子函数(子类)的属性和方法
let ldh = new LiuDeHua()
console.log(ldh.name) // 输出 刘德华
console.log(ldh.role) //输出 明星
ldh.singSong('忘情水') // 输出 忘情水

// 3. 总结
// 3.1 优点:
// (1)简单,子类实例既是子类的实例也是父类的实例
// (2)父类在原型上新增的方法和属性都能被子类获取到

// 3.2 缺点:
// (1)传参不方便,只能在继承的时候传递参数,无法在创建子类实例的时候传入参数
// (2)无法实现多继承(一个子类继承多个父类)
// (3)原型上的属性、方法被所有的实例共享
// 1. 定义好的类
function Star(name, sex) {
  this.name = name
  this.sex = sex
}
Star.prototype.role = '明星'
Star.prototype.singSong = function (song) {
  console.log('他唱的歌叫' + song)
}

// 2. 用原型链的方式实现继承
//   2.1 创建一个空的函数(子函数)
function LiuDeHua() {}
//   2.2 让子函数的原型指向构造函数,相当于在原型上 new 一个构造函数
//       让子函数的原型上拥有构造函数的全部属性和方法
LiuDeHua.prototype = new Star('刘德华', '男')
//   2.3 调用子函数(子类)的属性和方法
console.log(LiuDeHua.prototype.name) // 输出 刘德华
console.log(LiuDeHua.prototype.role) //输出 明星
LiuDeHua.prototype.singSong('忘情水') // 输出 忘情水

// 3. 总结
// 3.1 优点:
// (1)简单,子类实例既是子类的实例也是父类的实例
// (2)父类在原型上新增的方法和属性都能被子类获取到

// 3.2 缺点:
// (1)传参不方便,只能在继承的时候传递参数,无法在创建子类实例的时候传入参数
// (2)无法实现多继承(一个子类继承多个父类)
// (3)原型上的属性、方法被所有的实例共享

2.2 基于构造(.call .apply)继承

// 1. 定义好的 Star 类
function Star(name) {
  this.name = name
}
Star.prototype.role = '明星'

// 2. 定义好的 Star 类
function Sing(song) {
  this.sing = function () {
    console.log('他唱的歌有' + song)
  }
}

// ------------------------------------------

// 3. 用构造继承方式继承,也就是用 .call .apply,未用原型
function Stars(name, song) {
  Star.call(this, name) // 继承 Star 构造函数的属性或方法
  Sing.call(this, song) // 继承 Sing 构造函数的属性或方法
}

// 4. new 一个实例,并调用属性和方法
let LiuDeHua = new Stars('刘德华', '忘情水') // new 实例的时候传参
console.log(LiuDeHua.name) // 输出 刘德华
console.log(LiuDeHua.role) // undefined,也就是不能继承原型上的属性和方法
LiuDeHua.sing() // 输出 忘情水

// 4. 总结:
//    特点:可以实现多继承
//    缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法

2.3 组合继承

 同时使用上面构造继承和原型链继承。

优点: 1.传参方便,可以在创建实例时传参

            2.可以实现多继承

缺点: 1.无法继承父类原型上的属性和方法 

            2.因为原型上没有方法,所以无法实现函数复用

2.4 寄生组合继承(推荐)

// 1. 定义好的类
function Star(name, sex) {
  this.name = name
  this.sex = sex
}
Star.prototype.role = '明星'
Star.prototype.singSong = function (song) {
  console.log('他唱的歌叫' + song)
}

// 2. 寄生组合继承方式继承
//    2.1 先用构造继承,继承实例上的属性和方法,不继承原型上的
function LiuDeHua(name, sex) {
  // Star.call(this, arguments)// 使用 arguments,输出[Arguments] { '0': '刘德华', '1': '男' }形式
  Star.call(this, name, sex)
}

//    2.2 再用寄生继承,只继承原型上的
(function () {
  let temp = function () {}
  temp.prototype = Star.prototype
  LiuDeHua.prototype = new temp()
})()

// 3. new 实例,调用属性和方法测试
let ldh = new LiuDeHua('刘德华', '男')
console.log(ldh.name) // 刘德华
ldh.singSong('忘情水') // 他唱的歌叫忘情水
 
// 4. 总结:
// 通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的
// 构造的时候,就不会初始化两次实例方法/属性
// 实现麻烦

 

标签:function,ES6,prototype,Star,name,继承,sex,JS,class
来源: https://www.cnblogs.com/suihung/p/16219899.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有