2

类的创建

使用构造函数创建对象

构造函数是一种特殊的函数,主要用于初始化对象,一般与new关键字配合使用
new在执行时,首先创建一个对象,将this指向这个对象,然后执行构造函数的代码,给这个对象添加属性和方法并返回这个对象,所以构造函数不需要return

function Person(name,age){
    this.name = name;
    this.age = age;
    this.say =function hello(){
        console.log(name);
    }
}
let m = new Person("小明",18);
m.say();

构造函数

构造函数中可以添加一下成员与方法,也可以在构造函数本身上添加,通过这两种方式添加的成员,就分别称为静态成员和实例成员

  • 静态成员

在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问

Person.kind = "人类";
  • 实例成员

在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问

let m = new Person("小明",18);
m.say();

但是构造函数在创建对象时,会给所有方法创建开辟内存空间,造成内存的浪费

let m = new Person("小明",18);
let s = new Person("a",20);
console.log(s.say ===m.say);// false

在ES6中,创建对象可以用class关键字

class Person {
    constructor(name ,age){
        this.name = name;
        this.age = age;
    }

    say(){
        console.log(this.name);
    }
}
let person = new Person("ming",18);
person.say();

原型

构造函数原型 prototype

构造函数通过原型分配的函数是所有对象共享的,JavaScript中每个构造函数都有一个prototype属性,指向另一个对象,prototype是一个对象,这个对象所有的属性和方法,都会被构造函数所拥有。可以把那些不变的方法,直接定义在prototype对象上,这样所有的对象可以共享这些方法。

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.say=function(){
    console.log(this.name);
}

let person= new Person("xiao",18);
let person1= new Person("da",18);
person.say();//xiao
console.log(person.say ===person1.say);//true

对象原型 proto

对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型存在

  • __proto__对象原型和原型对象prototype是等价的
  • __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是他是一个非标准属性,因此实际开发中,不可以使用这个属性。
console.log(person.__proto__.say===Person.prototype.say);//true

同时原型对象持有一个constructor指向构造函数

console.log(Person.prototype.constructor === Person);//true

原型链

Person原型对象prototype也有__proto__对象,这个对象指向的是Object.prototype。而该对象的对象原型指向则是null,这样,就构成了一条原型链

成员查找按照原型链查找

  1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
  2. 如果没有就查找他的原型,即__proto__指向的prototype原型对象。
  3. 如果还没有就查找原型对象的原型(Object的原型对象)
  4. 以此类推一直找到null为止
  5. __proto__对象原型的意义就在于为对象成员查找机制提供了一个方向,或者说一条路线
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.length = "100";
Object.prototype.width = "200";
let person = new Person("ming",18);
console.log(person.age);//18
console.log(person.length);//100
console.log(person.width);//200

类的继承

ES6之前并没有extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

call()

调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg,arg1,arg2,...)
  • thisArg:当前调用函数this的指向对象
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.say=function(){
    console.log(this.name);
}

let person= new Person("小明",18);
let person1= new Person("大熊",18);

person.say();//小明
person.say.call(person1);//大熊

借用构造函数继承父类属性

通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性

function Father(name,age){
    this.name = name;
    this.age = age;
    this.say = function(){
        console.log(this.name);
    }
}
function Son(name,age,sex){
    Father.call(this,name,age);
    this.sex = sex;
}

let son = new Son("大熊",18,"男");

console.log(son.name,son.age,son.sex);//大熊 18 男
son.say();//大熊
console.log(son);//Son { name: '大熊', age: 18, say: [Function], sex: '男' }

还可以通过修改原型对象的方式,来添加原型链,从而获得父类方法

//此处不能直接指向Father的原型对象,否则在修改Son.prototype时,会改变父类的原型对象
Son.prototype = new Father();
Son.prototype.constructor = Son;

let son = new Son("小明",18,"男");
son.say();//小明

ES6类的继承

 class Father{
          money(){
            console.log(100);
          }
}
class Son extends Father{
}
let son = new Son();
son.money();

奶粥
6 声望0 粉丝

xiao海无涯苦揍舟~