在使用java语言的同时,也思考过怎么用js来进行面向对象的编程,JS在es6之后,引入了class和extend等关键词,我感觉它已经渐渐步入了面向对象编程语言的行列之中,但是在这之前,是怎么样进行一系列的面向对象操作的呢?这里我是看了阮一峰老师的教程而产生的总结:
一、封装
简单来说,按我的理解,封装就是将一系列的有特征的实例,抽象出来,形成一种模版,类似于java种的class。产生了这种模版之后,我们可以new出来。
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type="猫科动物"
Cat.prototype.eat = function() {
alert("吃老鼠")
}
在这里我们将一系列的实例抽象成Cat这个function(一般也认为是类),所以,我们new出来的实例,它都有这个模版的特征。
var cat1 = new Cat("123", "yellow")
var cat2 = new Cat("456", "blue")
console.log(cat1.name) //123
console.log(cat2.type) // 猫
这样的就叫封装了一个对象了,在java中就和这样类似
public class Cat {
private String name;
private String color;
private String type;
// .....get函数和set函数
private void eat() {
// .......
}
}
1.关键字prototype
在这里我们使用prototype关键字进行对一些不变属性的定义,这个关键字也会为以后的继承起到一定的作用。
我们创建的每个函数都有一个prototype
属性,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。那么,prototype
就是通过调用构造函数而创建的那个对象实例的原型对象。
使用原型的好处是可以让对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中添加定义对象信息,而是可以直接将这些信息添加到原型中。使用构造函数的主要问题就是每个方法都要在每个实例中创建一遍。
经验之谈: 把不变的属性和方法,绑在prototype对象上,而不能把可变属性绑上去。
2.关键字this
使用this了之后,在cat1和cat2实例中,都会有一个constructor属性,指向他们的构造函数,可以使用instanceof
关键字验证
alert( cat1 instanceof Cat); //true
alert( cat2 instanceof Cat); //true
3.isPrototypeOf()
这个方法用来判断实例是否继承与某个对象,也就是说判断某个proptotype对象和某个实例之间的关系。
alert(Cat.prototype.isPrototypeOf(cat1)); //true
alert(Cat.prototype.isPrototypeOf(cat2)); //true
4.hasOwnProperty() / in
运算符
这个方法用来判断一个实例的属性是自己的本地属性还是继承自父类对象的prototype的属性,in运算符来判断某个实例是否含有某个属性
alert(cat1.hasOwnProperty('name')) //true
alert(cat1.hasOwnProperty('type')) //false
alert("name" in cat1) // true
二、继承
1. 简单的prototype模式(构造函数继承)
现在有个父类,比如
function Animal() {
}
Animal.prototype.species = "动物"
要使新的子类Cat继承这个Animal
function Cat(name , color) {
this.name = name
this.color = color
}
var function f() {}
f.prototype = Animal.prototype
Cat.prototype = new f()
Cat.prototype.constructor = Cat
Cat cat1 = new Cat("123", "yellow")
console.log(cat1)
console的cat1
2. 深拷贝模式(非构造函数模式)
如果说我们的实例不是用new出来的,只是一个简简单单的纯对象,比如
var Chinese = {
nation: "中国"
}
var Doctor = {
career: "医生"
}
如果说我们要医生去继承中国,使之成为一个中国医生,一个很简单的方法就是x写一个object(),将子对象的prototype属性指向父对象
function object(o) {
var f = function() {}
f.prototype = o
return new f()
}
Doctor = object(Chinese)
Doctor.carrer = '医生'
同样的我们也可以采用拷贝模式,把父类所有的属性拷贝到子对象,这也是lodash源码中assign方法中所使用的方案。
function extend(p, c) {
var c = c || {}
for (var i in p) {
if(typeof p[i] === 'object') {
c[i] == (p[i].constructor === 'Array' ? [] : {})
extend(p[i], c[i])
} else {
c[i] = p[i]
}
}
return c
}
网友评论