2

JavaScript的面向对象与其他语言的面向对象,其实有很大的区别。

JavaScript是基于原型的面向对象系统,而传统语言(比如java)的面向对象都是基于类的。

构造函数

function Person(name, age, job) {
    this.age = age;
    this.name = name;
    this.job = job;
}

Person.prototype.sayName = function() {
    console.log(this.name);
}
var cody = new Person('cody', '24', 'frontend');
cody.name;
cody.sayName();

在这个常见的构造函数写法中,我们需要知道以下几点:

1.Person这个函数被定义后,会自带一个prototype属性,这个属性指向一个对象,既原型对象,这个对象同时有一个constructor属性,指向Person

Person.prototype = {
    constructor: Person
}

注意的是,所有函数都有prototype属性,并不是只有构造函数才有。

2.cody这个通过构造函数生成的对象,有一个__proto__属性,它指向构造函数Person的原型对象,既Person.prototype
访问cody.name时,在它自身寻找该属性,找到了,于是就返回该值。
访问cody.sayName时,也是先在它自身寻找该属性,但是无法找到,于是开始通过原型链向上寻找: 寻找cody.__proto__,也就是Person.prototype原型对象,发现了该属性,于是返回这个方法。
访问cody.toString时,在Person.prototype原型对象上也找不到,这时,继续向上寻找,既寻找Person.prototype.__proto__也就是Object.prototype,在它上面,可以找到toString

继承

function Animal(name) {
    this.name = name;
}
Animal.prototype.sayName = function() {
    console.log(this.name);
}

function Duck(name, color) {
    Animal.call(this, name);
    this.color = color;
}

Duck.prototype = new Animal();
// 也可以优化成这样,减少一次父级构造函数调用
// Duck.prototype = Object.create(Animal.prototype);
Duck.prototype.constructor = Duck;
Duck.prototype.sayColor = function() {
    console.log(this.color);
}
var duck = new Duck('duck', 'yellow');
duck.sayColor();
duck.sayName();

前面我们说过,JS是基于原型的面向对象。所以,继承并不一定需要使用构造函数,我们可以基于一个已经存在的对象,对这个对象进行继承。

var obj = {
    name: 'cody',
    say: function() {
        console.log(this.name)
    }
};

var sub = Object.create(obj);
sub.name = 'deepred';
sub.say(); // deepred

Object.create的原理是:

Object.create = Object.create || function(obj) {
    var F = function() {};
    F.prototype = obj;

    return new F();
}

ES6的class语法

ES6引入了class语法,让JS看起来更像是面向对象的语言,但这仅仅是语法糖而已,背后仍然是基于原型的继承方式。

class Animal {
    constructor(name) {
        this.name = name;
    }
    sayName() {
        console.log(this.name)
    }
}

class Duck extends Animal {
    constructor(name, color) {
        super(name);
        this.color = color;
    }

    sayColor() {
        console.log(this.color);
    }

    sayName() {
        // 调用父级同名方法
        super.sayName();
        console.log('duck sayname')
    }
}
var duck = new Duck('duck', 'red');
duck.sayColor();
duck.sayName();

深红
2k 声望324 粉丝

萌豚