原型链继承

  1. /*1.原型链继承*/
  2. function parent(){
  3. this.name = 'parent'
  4. }
  5. parent.prototype.getname = function(){
  6. console.log(this.name)
  7. }
  8. function child(){
  9. parent.call(this)
  10. }
  11. child.prototype = new parent()
  12. var child2 = new child()
  13. child2.getname() //parent
  14. /*
  15. 由于new出来的是一个对象,所以必须要用对象名.key的方式访问
  16. */
  17. /*
  18. 1.引用类型的属性被所有实例共享,举个例子:
  19. */
  20. var child3 = new child()
  21. child3.getname() //parent
  22. child3.name = '3'
  23. child2.getname() //3
  24. child3.getname() //3
  25. /*
  26. 在创建 Child 的实例时,不能向Parent传参
  27. */
  28. function parent2(){
  29. this.name = 'parent2'
  30. }
  31. function child4(){
  32. parent2.call(this)
  33. }

借用构造函数继承

  1. function parent(){
  2. this.name = ['parent','1']
  3. }
  4. function child(){
  5. parent.call(this)
  6. }
  7. var p1 = new child()
  8. var p2 = new child()
  9. p1.name.push('p1')
  10. p2.name.push('p2')
  11. console.log(p1.name)
  12. console.log(p2.name)
  13. // ["parent", "1", "p1"]
  14. // ["parent", "1", "p2"]
  15. /*
  16. 优点:
  17. 1.避免了引用类型的属性被所有实例共享
  18. 2.可以在child中向parent传参
  19. */
  20. /*
  21. 缺点:方法都在构造函数中定义,每次创建实例都会创建一遍方法。
  22. */

原型式继承

  1. /*
  2. es5 Object.create模拟实现
  3. */
  4. function objectcreate(object){
  5. function f(){}
  6. f.prototype = object
  7. return new f()
  8. }
  9. var obj = {
  10. name : '123',
  11. age : [17,18]
  12. }
  13. var p1 = objectcreate(obj)
  14. var p2 = objectcreate(obj)
  15. p1.name = '456'
  16. console.log(p2.name) // 123
  17. p1.age.push('p1')
  18. console.log(p2.age) // [17, 18, "p1"]
  19. //缺点:包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。

寄生式继承

  1. //寄生式继承
  2. function createobj(o){
  3. var clone = Object.create(o)
  4. clone.sayName = function(){
  5. console.log('hi')
  6. }
  7. return clone
  8. }
  9. //创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。
  10. // 缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

组合继承

  1. /*
  2. 原型链继承和经典继承双剑合璧。
  3. */
  4. var parent = function(){
  5. this.name = parent
  6. this.color = ['red','blue']
  7. }
  8. parent.prototype.getname = function(){
  9. console.log(this.name)
  10. }
  11. var child = function(name,age){
  12. parent.call(this,name)
  13. this.age = age
  14. }
  15. child.prototype = new parent()
  16. var p1 = new child()
  17. var p2 = new child()
  18. console.log(p1)
  19. console.log(p2)
  20. //child {color: Array(2), age: undefined, name: ƒ}
  21. //child {color: Array(2), age: undefined, name: ƒ}
  22. //优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式
  23. // 组合继承最大的缺点是会调用两次父构造函数。

寄生组合式继承

  1. /*组合继承
  2. function parent(name,color){
  3. this.name = name
  4. this.color = ['red','blue']
  5. }
  6. parent.prototype.getname = function(){
  7. console.log(this.name)
  8. }
  9. function child(name,age){
  10. parent.call(this,name)
  11. this.age = age
  12. }
  13. child.prototype = new parent()
  14. var child1 = new child('kevin', '18');
  15. console.log(child1)
  16. */
  17. /*
  18. 组合继承最大的缺点是会调用两次父构造函数。
  19. 一次是设置子类型实例的原型的时候:
  20. child.prototype = new Parent();
  21. 一次在创建子类型实例的时候:
  22. var child1 = new child('kevin', '18');
  23. 回想下 new 的模拟实现,其实在这句中,我们会执行:
  24. parent.call(this, name);
  25. 在这里,我们又会调用了一次 Parent 构造函数
  26. 所以,在这个例子中,如果我们打印 child1 对象,我们会发现 child.prototype 和 child1 都有一个属性为colors,属性值为['red', 'blue', 'green']。
  27. console.log(child.prototype)
  28. console.log(child1)
  29. */
  30. /*
  31. 寄生组合式继承
  32. */
  33. function parent(name,color){
  34. this.name = 'parent'
  35. this.color = ['red','blue']
  36. }
  37. function child(name, age) {
  38. parent.call(this, name);
  39. this.age = age;
  40. }
  41. function createobj(o){
  42. function f(){}
  43. f.prototype = o
  44. /*
  45. {constructor: ƒ}
  46. constructor: ƒ parent(name,color)
  47. __proto__: Object
  48. */
  49. return new f()
  50. }
  51. function prototypeobj(child,parent){
  52. var prototype = createobj(parent.prototype)
  53. prototype.constructor = child
  54. child.prototype = prototype
  55. }
  56. prototypeobj(child,parent)
  57. var p1 = new child()
  58. var p2 = new child()
  59. p1.name = 'p1'
  60. p2.name = 'p2'
  61. console.log(p1)
  62. console.log(p2)
  63. //child {name: "p1", color: Array(2), age: undefined}
  64. //child {name: "p2", color: Array(2), age: undefined}
  65. /*
  66. 寄生组合原理:
  67. p1的constructor为child,__proto__中的constructor为parent
  68. createobj(parent.prototype) 这一步的功能是创建一个对象,这个对象是parent的实例,具有parent的constructor方法
  69. prototype.constructor = child 这一步将prototype的constructor设为child函数
  70. child.prototype = prototype 设置child的原型为prototype 这样child就继承了parent的constructor
  71. 通过prototypeobj方法,child的prototype有了两个constructor,一份是原本自己的,另一份通过__proto__ 寻找到父级的constructor
  72. */
  73. /*
  74. 三步骤
  75. 首先先创建个变量
  76. var prototype = Object.create(父类的prototype)
  77. prototype.constructor = child(子类的constructor)
  78. child.prototype(子类的prototype) = prototype
  79. */

es6 extend

  1. class Point{
  2. constructor(x){
  3. this.x = x;
  4. this.p = 2;
  5. this.j = 3;
  6. }
  7. print(){
  8. return this.x
  9. }
  10. m(){
  11. return this.p
  12. }
  13. static b(){
  14. console.log(this.c())
  15. }
  16. static c(){
  17. return 'world'
  18. }
  19. }
  20. Point.prototype.z = 2
  21. //调用
  22. var p1 = new Point('p1') //更es5一样,调用Point构造函数new一个实例对象
  23. console.log(p1)
  24. //Point {x: "p1", p: 2}
  25. /*
  26. constructor是该类的构造函数,即使你没有创建,系统也会自动生成一个。一般 constructor 方法返回实例对象 this ,但是也可以指定 constructor
  27. 方法返回一个全新的对象,让返回的实例对象不是该类的实例。
  28. */
  29. /*
  30. 上面的代码用es5可以这样表达
  31. function Point(x){
  32. this.x = x;
  33. this.p = 2;
  34. }
  35. Point.prototype.print = function(){
  36. return this.x
  37. }
  38. */
  39. /*
  40. super
  41. */
  42. /*
  43. 函数时使用
  44. super只能在子类的constructor使用,不能在别的方法调用
  45. */
  46. class colorPoint extends Point{
  47. constructor(x){
  48. super(x) // 调用父类的constructor(x)
  49. this.y = 2
  50. super.y = 3
  51. }
  52. b(){
  53. console.log(super.print()) //调用父类的print() this指向子类colorPoint的实例
  54. console.log(super.m()) //调用父类的m() 结果是2
  55. console.log(super.z) //获取父类的prototype.z属性
  56. }
  57. }
  58. let p2 = new colorPoint('p2')
  59. //colorPoint {x: "p2", p: 2}
  60. /*
  61. 对象时使用
  62. super.print(),将super当作一个对象使用,super指向Point.prototype,此时print就是Point.prototype.print方法
  63. super.z 由于super指向Point.prototype,此时z就是Point.prototype.z
  64. super.y赋值为3,这时等同于对this.y赋值为3。而当读取super.y的时候,读的是A.prototype.y 显示为undefined
  65. */
  66. /*
  67. Object.getPrototypeOf方法可以用来从子类上获取父类
  68. */
  69. Object.getPrototypeOf(colorPoint) === Point //true
  70. /*
  71. static 静态方法
  72. static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
  73. 1.可以被子类继承
  74. 2.只能通过类调用
  75. 3.this指本类,不指实例
  76. 4.通过this调用只能调用本类定义的static方法
  77. */
  78. Point.b()
  79. // world
  80. colorPoint.b()
  81. // world
  82. /*
  83. new.target
  84. new.target属性允许你检测函数或构造方法是否通过是通过new运算符被调用的。
  85. */