JavaScript
号称万物皆对象,但是面向对象编程并不是它的主要的编程哲学。每种语言都有自己最合适的编程方法,而JS
并不是为了面向对象而生的,所以不要强行去使用面向对象,不要为了OOP
而OOP
。其实它更加的偏向于函数式编程,但是对这种也有一定的支持。
自定义对象
对于内置对象其实一直在默默发挥作用,其实还可以自定义自己的对象来完成指定的某种操作。JS
中没有声明语句没有类的定义,它基于原型可以让一个对象作为原型类似于类的定义,然后使用的时候让新的对象以它为原型就实现了自定义的类。
构造器
function Person() {
this.name = '';
this.say = function () {
console.log('hello!');
};
}
// new with constructor
var wong = new Person();
new
关键字在这种语言里面得到了很大的拓展,它充当了一个构造器的作用来构造对象。
属性
属性就是这个对象所包含的一些信息了,这个信息可以是真正的属性,也可以是该对象的方法。
对象属性
这属性就像是之前的那种私有变量或者公有变量一样。
var a = new Person();
a.name = 'Wong';
但是在JavaScript
中的属性并不局限于构造函数中或者类定义中的这些属性,而是随时可以添加的。
a.age = 19;
// add properties directly
方法
方法与属性很相似, 不同的是一个是函数,另一个可以被定义为函数。后者算是一种属性,前者是绑定在类对象上的函数也称作方法,有一点小差别。
Person.prototype.sayHello = () => {
alert('hello!');
};
a.sayHello(); // called through an object
a.say();
var b = a.sayHello;
var c = a.say; // called separately
可以把方法从对象中剥离出来也是有风险的,对象的方法如果具有this
指针那么脱离context
环境就会无法指向。
this
的指向
如果脱离了对象,它将会指向全局,如果是浏览器则会指向window
。
类继承
继承在JavaScript
中是一件比较让人头疼的事情,通常不能够像其他语言一样比较简洁的继承,但是在ES6
标准中也重新提供了一种继承的语法糖。
原型链继承
JS
中没有类这一说,只有原型对象的存在,继承类也就是说继承原型中的某些方法或者属性。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function () {
console.log(`My name is ${this.name}.`);
};
Parent.prototype.doSomething = function () {
console.log('Doing something...');
};
// Prototype chain inheritance and set up prototypes for son class.
function Child(name) {
this.name = name;
}
Child.prototype = new Parent('Tom');
Child.prototype.constructor = Child;
类式继承
这种继承必须重写所有的父类方法,不能够很好的实现继承,而且没有实现代码的重用。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function () {
console.log(`My name is ${this.name}.`);
};
Parent.prototype.doSomething = function () {
console.log('Doing something...');
};
function Child(name, parentName) {
// Call the constructor of the parent class.
Parent.call(this, parentName);
this.name = name;
}
Child.prototype.sayName = function () {
console.log(`Child's name is ${this.name}`);
};
Child.prototype.doSomething = function () {
console.log('Doing something...');
};
组合继承
组合继承就是前两种继承的结合体,进一步的解决了前两种继承的缺点,也是JavaScript
中最为常用的继承方法。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function () {
console.log(`My name is ${this.name}.`);
};
Parent.prototype.doSomething = function () {
console.log('Doing something...');
};
function Child(name, parentName) {
// Give arguments to the base class constructor.
Parent.call(this, parentName);
this.name = name;
}
Child.prototype = new Parent();
// Call constructor of base class, this step is to get method of base class.
Child.prototype.constructor = Child;
原型的解析
原型链为什么可以实现方法属性上的继承?作为一种动态语言,对象调用函数时会沿原型链查找对应函数。当然这也是为什么JavaScript
只能够单继承,因为上面有且只能有一条原型链对应。