写了几篇 vue 入门的内容了,今天写点其它的放松一下,简单讲讲 javascript 中的面相对象。
在面向对象的语言中,都有类的概念,当然 es6 中开始 javascript 中也有类的概念了,这里以 es5 为基础开始讲解,毕竟当前即使写的 es6 代码,一般还是会通过 babel 等转码器翻译到 es5 来执行的;
在 js 中虽然没有类的概念,但是我们却可以创建对象,一般创建对象有两种方式(这里指自定义对象):
1、使用构造函数
- function Person() {
- }
- var p = new Person();
2、使用字面量
- var p = {
- //各种属性
- }
这里着重介绍一下构造函数方式创建对象;以上面代码为例,function Person(){}, 这个和普通函数有什么区别么?其实除了命名约定外(建议首字母大写)声明上没有任何区别,主要是调用方式的不同,构造函数调用使用 new 操作符,使用 new 操作符调用构造函数,主要经过四个步骤:
1)、创建一个新的对象;
2)、把 this 指向新对象;
3)、给对象添加属性
4)、返回新对象
对我们上面的代码进行一点简单的修改:
- function Person(){
- this.name= "zhangsan";
- this.age=10;
- };
- var p=new Person();
- console.log(p.name,p.age) ;//'zhangsan 10'
再对比上面使用 new 操作符调用构造函数的过程,是不是很容易理解输出的结果。
刚才也说了,构造函数和普通函数调用完全相同,那么是不是说可以把构造函数进行普通调用呢?当然可以,对我们的例子再次进行修改:
- function Person(){
- this.name= "zhangsan";
- this.age=10;
- };
- //var p=Person();
- Person();
- console.log(window.name,window.age) ;//'zhangsan 10'
不使用 new 操作符调用,不会经过上述四个步骤的隐式处理,所以这个时候不会有新对象的创建和 this 指向的改变,那么此时的 this 就指向了全局对象,在浏览器中即 window 对象,所以可以使用 window.name 来访问,得到正确的输出。
OOP 三大特性:封装、继承、多态;这里只讲述在 javascript 中如何进行继承(限 es5)。
继承只是是代码重用的一种手段,那么在 js 中如何实现继承呢?
基于原型的继承
首先,函数也是对象,因为所有函数都是 Function 对象的实例,function 函数名,这种方式定义函数只是一种快捷方式,理论上和 var 函数名 = new Function(p1,body) 等价,从这一点上看函数名其实就是指向函数的指针,但是两者不同的是,通过 new Function 来创建函数,会被 js 解释器解释两次,一次是声明时,第二次是对 body 部分的解析。
其次,任何一个函数创建后,都有一个原型对象,如:
声明一个 Person 函数,那么我们可以使用 Person.prototype 来打印一下其原型对象,可以看到其原型对象是一个 Object 类型,里面包括一个属性(不算__proto__, 这个术语内部变量,是实例到原型的指针)constructor,指向了函数 Person;另外原型对象本身就是另一个对象的实例(这是是 Object 函数的实例,=new Object()),任何一个对象的实例,都包含一个内部变量__proto__(chrome 浏览器)(Object.create(null) 创建的对象除外),指向创建这个对象实例的类型的原型,此处__prop__指向的是 Object.prototype. 而且可以看到 Object.prototype 上包含的几个方法(toString、valueOf 等)。
上面说了任何一个对象的实例,都包含一个指向其构造函数原型的内部变量,那么我们创建一个 Person 的实例:
可以看到是同一个,所以我们可以总结构造函数、实例、和构造函数原型之间的关系如下:
虽然画的是很难看,但是我觉得应该也表达出我要表达的意思了啊,
来源: http://www.cnblogs.com/Johnzhang/p/7294632.html