--- title: 面向对象编程 date: 2017-12-20 20:26:42 tags: - JavaScript categories: - JavaScript --- 面向对象的两个基本概念 1. **类** : 是对象的类型模板 , 是一种抽象 , 并不表示实体 2. **实例** : 是根据类创建的对象 , 表示某个具体的事物 类和实例是大多数面向对象编程语言的基本概念。 不过,在JavaScript中,这个概念需要改一改。JavaScript不区分类和实例的概念,而是通过`原型(prototype)`来实现面向对象编程。 既然没有类的概念 , 我们就需要用某个对象来模拟一个类了 ```javascript var person = { name : "Unnamed", run : function(){ console.log(this.name + "is running..."); } }; //现在我们可以把person来当做一个原型对象, 来创建一个具体的"人" var xiaoming = { name : "小明" }; xiaoming.__proto__ = person; ``` JavaScript当中的原型链 , 既可以模拟由类创建实例的关系 也可以模拟继承的关系 原型对象本身也可以有原型对象 , 从而构成`原型链` 默认原型对象是`Object` 当然在运行中也可以随时改变某个对象的原型对象 > 以上代码主要用于表示原型链的实际关系 , 实际编程当中最好不要直接去修改对象的`__proto__` > `Object.create()`方法可以传入一个原型对象 , 用来构造出一个新对象 ```javascript var xiaoming = Object.create(person); xiaoming.name = "小明"; //验证原型对象 xiaoming.__proto__ === person; //true ``` 当我们访问某个对象的属性时 , 例如`obj.xxx` js引擎会先在该对象上查找该属性 , 如果没找到 , 就会到原型对象上去找 , 也就是顺着原型链一直向上回溯 , 直到`Object.prototype`对象 , 如果还没有 , 那么就是undefined 除此之外 , 也可以使用`构造函数`来创建对象 构造函数本身和普通的函数没什么区别 , 只是用**new**关键字来调用 , 就会返回一个需要构建的对象 ```javascript function Student(){ this.name = "sookie"; this.age = 18; this.say = function(){ alert("Hello"); } } var stu = new Student(); stu.say(); ``` 如果按照普通函数的调用方式执行调用 , 其中的this就表示window对象 那么其中代码的效果就是定义了几个全局属性 如果使用 new 来调用该函数 , 那么它绑定的this就指向新创建的对象 并默认返回this ( 不需要写return ) 使用这种方式创建的对象还从原型上获得了一个 constructor 属性 指向这个构造函数本身 ![constructor](/images/JavaScript/OOP1.png) —> 另外这个对象中有一个 say 属性 , 它是一个函数 在这种情况下 , 这个函数是属于stu对象的 , 并不属于该对象的原型 如果使用原型创建了多个对象 , 其中就会有很多重复的函数 所以可以把这个函数放入到Student的prototype当中 ```javascript function Student(){ this.name = "sookie"; this.age = 18; } Student.prototype.say = function(){ alert("Hello"); } var stu1 = new Student(); var stu2 = new Student(); console.log(stu1.say == stu2.say) //true ``` ![prototype](/images/JavaScript/OOP2.png)