一、关于类

所 “类” 谓就是对象的模板,对象就是“类”的实例,而Javascript在es6之前没有类这个概念,Javascript使用构造函数来模拟Java中的类

1-1 构造函数

定义:就是构造一个对象的函数(java—构造函数和类名相同)

  1. function Person(name,age){
  2. this.name=name;
  3. this.age=age
  4. }
  5. /* 使用new关键字去实例化对象 */
  6. var zhang=new Person("zhangsan",18);
  7. console.log(zhang)

1-2 构造函数的特点

  1. 函数体内部使用了this关键字,代表了所要生成的对象实例。
  2. 生成对象的时候,必须使用new命令
  3. 在构造函数中 谁使用new关键字调用构造函数,this就指向谁


1-3 new命令的原理

使用new命令时,它后面的函数一次执行下面的步骤

  1. 创建一个对象实例
  2. 实例化对象的原型指向构造函数的原型对象

    1. console.log(chengchao.__proto__== Person.prototype)
  3. 将这个对象赋值给构造函数的this

    二、原型

    **JavaScript的继承是基于原型的继承
    JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。
    只要在原型对象上设置一个方法,所有的对象都用有这个方法

    1. var arr=new Array(1,2,3);
    2. Array.prototype.sayHello=function(){
    3. console.log("hello")
    4. }
    5. var a=[4,5,6]
    6. arr.push(4) //push也是写在原型上的
    7. arr.sayHello() //在原型上添加的方法,输出:hello
    8. a.sayHello() //hello
  1. var Person = function(name,age){
  2. this.name = name;
  3. this.age = age;
  4. }
  5. var pengzhengang = new Person("name",18)
  6. console.log(pengzhengang.name); //"程超"
  7. console.log(pengzhengang.age); //18

三、原型链,继承

3-1 原型链

  • JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型
  • 所有对象皆有proto属性,它指向它的原型对象

3-2 继承

  • 每一个对象都会有一个隐藏属性proto,它指向它的原型对象
  • 这个对象会享有原型上的属性或者方法

    1. <script>
    2. /* 为什么一个实例化的对象能够使用它原型上的方法 */
    3. function Person(name,age){
    4. this.name=name;
    5. this.age=age;
    6. }
    7. Person.prototype.sayName=function(){
    8. console.log(this.name)
    9. }
    10. /*
    11. 1.每一个对象都有一个隐藏属性__proto__,它指向它的原型对象
    12. 2.这个对象会享有原型上的属性或者方法
    13. */
    14. var peng=new Person("pengzhengang",18)
    15. console.log(peng)
    16. console.log(peng.__proto__)
    17. console.log(peng.__proto__==Person.prototype)
    18. </script>
  • 如果一个对象自身没有一个方法,它就会从它的原型上去找

  • object.prototype是终点,是源头 ,没有proto属性

十一、面向对象 - 图1

四、ES6实现一个Class

使用extends关键字可以实现继承,之后可以自动拥有父类的属性和方法

  1. <script>
  2. /* 面向对象的方法
  3. function Person(name,age){
  4. this.name=name;
  5. this.age=age;
  6. }
  7. Person.prototype.sayName=function(){
  8. this.name;
  9. } */
  10. /* es6的方法 */
  11. class Person{
  12. constructor(name,age){
  13. this.name=name;
  14. this.age=age;
  15. }
  16. sayName(){
  17. console.log(this.name) //lisi
  18. }
  19. }
  20. /* 使用extends关键字可以实现继承,之后可以自动拥有父类的属性和方法 */
  21. class Student extends Person{
  22. constructor(name,age,skill){
  23. super(name,age); //super指的是Person
  24. this.skill=skill
  25. }
  26. /* //子类下的函数:这种写法是错误的
  27. saySkill(){
  28. console.log(this.skill)
  29. } */
  30. }
  31. var zhang=new Person("zhangsan",18);
  32. // /* 父类不能使用子类的方法,子类可以使用父类的方法 */
  33. // zhang.saySkill()
  34. var s=new Student("lisi",17,"html")
  35. s.sayName()
  36. console.log(s) //Student("lisi",17,skill:"html")
  37. </script>

在子类的方法中去调用父类的方法—this

  1. class Person{
  2. constructor(name,age){
  3. this.name=name;
  4. this.age=age;
  5. }
  6. sayName(){
  7. console.log(this.name)
  8. }
  9. }
  10. /* 在子类的方法中去调用父类的方法 */
  11. class Student extends Person{
  12. constructor(name,age,skill){
  13. super(name,age); //super指的是Person
  14. this.skill=skill
  15. }
  16. saySkill(){
  17. this.sayName()
  18. }
  19. }
  20. var peng=new Student("lisi",17,"html")
  21. peng.saySkill()
  22. var p=new Person("zhangsan",18)
  23. console.log(Person.prototype)

五、static

5-1 静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为 “静态方法”

  1. class Father {
  2. static testMethod() {
  3. return 'hello';
  4. }
  5. }
  6. //通过类名直接调用
  7. Father.testMethod() // 'hello'
  8. var Child = new Father();
  9. Child.testMethod()
  10. // TypeError: Child.testMethod is not a function
  11. //这是因为Father中的testMethod方法是静态方法(有static关键字),不会被实例化出来的Child继承

5-2 静态属性和实例属性

静态属性指的是Class本身的属性,即Class.propname,而不是定义在实例对象(this)上的属性

  1. // StaticMethod.js
  2. // 定义静态属性
  3. StaticMethod.firstName = 'pca';
  4. console.log(StaticMethod.firstName);
  5. // 定义实例属性
  6. // ES6实例属性只能在constructor构造函数中定义
  7. constructor() {
  8. super();
  9. this.width = '40cm';
  10. }
  11. getWidth(){
  12. return this.width;//使用的时候需要加上this
  13. }
  14. // 为了可读性的目的,对于那些在constructor里面已经定义的实例属性,新写法允许直接列出。
  15. width;

5-2 static继承

父类的静态方法可以被子类继承

  1. class Father {
  2. static testMethod() {
  3. return 'hello';
  4. }
  5. }
  6. class Child extends Father {
  7. }
  8. Child.classMethod(); // 'hello'
  9. //上面代码中,父类Father有一个静态方法,子类Child可以调用这个方法,因为这是通过extends继承的,不是通
  10. new()实例化得到的