面向对象与面向过程
同:都是一种编程思想
异:
面向对象:
-
一切皆对象,每个对象负责自己的行为,任何东西可以抽象成类和对象的概念,同时也能向其它对象发送消息,从而实现相互协作。面向对象强调继承、封装、多态等概念。
-
面向对象的设计更加灵活,可复用性高。
-
学好面向对象:Java和设计模式。
面向过程:
1、注重过程,以步骤为中心,以数据为重点,依次执行一系列操作。
2、更加直观,容易实现。但是也容易写成面条式代码。
面向对象的基础:函数对象
- 面向对象的第一步:对象的生成。在其它语言中是通过实例化一个模块生成对象,而js是通过函数生成一个对象,即函数对象。
- 函数对象,即用来生成对象的构造函数。
- js的对象有2种:①简单对象②函数对象。那么为什么用简单对象不能实现面向对象呢?因为面向对象的基础是组件化、实例化、实例间互不干扰。而用简单对象,任何一个实例修改了对象,其它所有实例也被修改了,所以无法用简单对象实现。而用函数对象,每一个实例间不会互相影响。
- 一个vue组件本质就是一个对象,生命周期=构造函数内的一个构造步骤,methods=对象下面的方法,props、data=对象的属性。每个组件间互不影响,因为每个组件都被实例化了,它并不是挂载在全局的一个变量。
- js本质并不是基于类,基于构造函数+原型链。
原型链
-
本质:通过链式结构,指针的方式,公用内存地址的方式,一代代继承下来。
-
定义:每个对象都有隐式原型__proto__,它指向构造函数的原型对象,即prototype,原型对象也有__proto__,它又指向构造函数的构造函数的原型对象.....。这样就构成了一个链条。查对象属性或方法时,我们先去这个对象里去找,如果没有的话就去它的原型对象里找,如果还是没有的话再去向原型对象的原型对象里去寻找… 。
-
相关知识点:
- 每个构造函数都有一个prototype对象。
- prototype对象上有一个constructor属性,指向构造函数。
- 每个实例/对象都有一个__proto属性,指向构造函数的prototype;有一个constructor属性,继承自原型对象,指向了构造函数的引用。
- 实例.proto <=> 原型.prototype,即指向同一个内存地址。
- Object既是构造函数又是对象,即是函数对象。
- 首先:js中先创建的是Object.prototype这个原型对象。
- 然后:在这个原型对象的基础之上创建了Function.prototype这个原型对象。
- 其次:通过这个原型对象创建出来Function这个函数。
- 最后: 又通过Function这个函数创建出来之后,Object()这个对象。 原型链图
创建一个对象的3种方式
- Object.create()
const a = Object.create(b); // 代表着a对象的原型链,指向b对象 a.__proto__ = b;
- new Obj()
function Person(name) {
this.name = name;
}
const p = new Person('菜鸡');
// 1. new 创建了一个对象,这个对象,指向了构造函数的原型。
p.__proto__ === Person.prototype;//Person.prototype是一个对象
// 2. 构造函数上,有个 原型 prototype , 原型里面,有个 constructor 函数,就是 构造函数自己。
Person.prototype.constructor === Person;
// 3. p 的构造函数,是 Person
p.constructor === Person;//p上面没有constructor,回去原型链上找,找到了Person。
- var bar = {}
// -> 意味着,bar 的原型链,指向了 Object 的原型
// bar.__proto__ === Object.prototype;
- 用new的方式来模拟实现Object.create
function inherit(p) {
if(Object.create) {
return Object.create(p);
};
function f() {};
f.prototype = p;
f.prototype.constructor = f;
return new f();
}
const a = inherit(b);
继承
- 构造函数的继承
- 原型链继承
- 构造函数继承(经典继承)
- 组合继承
- 寄生组合继承
- 多重继承
- 拷贝继承
- 非构造函数的继承
- 定义:两个对象都是普通对象,不是构造函数,无法使用构造函数方法继承。
- 方法:
- object方法
- 浅拷贝继承
- 深拷贝继承
以上,可具体参考阮佬的文章。www.ruanyifeng.com/blog/2010/0…
new关键字
- 做了哪几件事
const p = new Person();
p.__proto__ === Person.prototype;
Person.prototype.constructor === Person;
p.constructor === Person;
- 创建一个对象
- 该对象,实现了这个构造函数的方法
- 这个对象的隐式原型指向了这个Function的prototype
- 根据一些特定情况,返回:
- 如果没有返回值,则返回我创建的这个对象
- 如果返回了一个基本类型,则仍然返回我创建的这个对象
- 如果返回了一个对象,则返回这个对象
- new后面的,必须是一个函数
- 实现一个new关键字
function newFunc(Father) {
// 1. 必须要是个函数
if(typeof Father !== 'function') {
throw new Error('new operator function the frist param must be a function');
};
// 3.这个对象的原型,指向了这个 Function 的 prototype;
var obj = Object.create(Father.prototype);
// 该对象,实现了这个构造函数的方法;即执行了Father方法。
// result 是 我在执行 Father 函数之后,得到的返回值。
var result = Father.apply(obj, Array.prototype.slice.call(arguments, 1));
// 根据一些特定情况,返回
return result && typeof result === 'object' ? result : obj;
}
对象的封装
详情可以参考阮一峰大佬的文章:www.ruanyifeng.com/blog/2010/0…
对象上的一些函数
- instanceof
- isPrototypeOf
- hasOwnProperty,验证一个属性是本地属性还是继承属性
- in,用于判断对象是否含有某个属性,不管是本地还是继承属性;还可以用于对象遍历。
其它get
- 如果对象上没有某个属性/方法,则去原型上面找
- 函数有两个功能:作为构造函数和可执行函数
- Object是所有对象的鼻祖