面向对象编程及原型链介绍

7 篇文章 0 订阅
1 篇文章 0 订阅

什么是面向对象编程

对比面向过程编程

面向过程:关注的重点是动词,是分析出解决问题需要的步骤,编写对应的函数来实现每个步骤,依次来调用函数。

面向对象:关注的终点是主谓,把问题分解成各个对象,每个对象表示在具体步骤内的各种行为。

面向对象的三大特性:

1.封装:让使用对象的人不考虑内部实现,只考虑功能使用,把内部的代码保护起来,只留出一些api供使用方使用。

2.继承:为了代码复用,从父类上继承出一些方法和属性,子类也有自己的一些属性。

3.多态:是不同对象作用同一操作产生的不同结果,多态的思想实际上是把”想做什么“和”谁去做“分开。

什么时候适合使用面向对象的思想

1.在比较复杂的问题面前,或者说参与方较多的时候,面向对象可以很好的简化问题,能够更好的扩展和维护。

2.在比较简单的问题面前,也可以一步步的按照步骤调用,用面向过程。

创建对象的几种方式

1.普通方式

很不灵活,如果再创建一个黑棋选手,则需要重新写

const Player = new Object();
Player.color = 'white';
Player.start  = function() {
	console.log('white下棋');
}

2.工厂模式

或者工厂模式,这两种方式都无法识别对象类型,比如 Player 的类型只是 Object

function createObject(color) {
	const Player = new Object();
    Player.color = color;
    Player.start = function() {
        console.log(this.color+'下棋')
    }
    return Player;
}

3.构造函数

缺点:this挂的属性/对象,都是指向当前对象的,所以在实例化的时候,通过this添加的属性或者方法,就会在内存中 创建一份。

function Player(color) {
	this.color = color;
    this.start = function() {
        console.log(this.color+'下棋');
    }
}

4.原形

优点:start方法只会在内存中存一份

function Player(color) {
    this.color = color;
}
Player.prototype.start = function() {
    console.log(this.color+'下棋');
}

const white = new Player('white');
const black = new Player('black');

white.start();
black.start();

5.静态属性

绑定 构造函数上的属性方法,需要通过构造函数访问。

function Player(color) {
	this.color = color;
    if(!Player.count){
        Player.count = 0;
    }
    Player.count++;
}

手写一个new方法

new的本质是:

1.创建一个新的空的object对象p1

2.将构造函数的原型对象赋值给新的p1的proto

3.将this指向新的p1对象

4.有return的情况

​ 1.如果显性的return为一个非object类型,则返回p1对象

​ 2.如果显性的return为一个object类型,则返回当前object对象

function createNewObject() {
	let p1 = {};
	const playerConstructor = [].shift.call(arguments); // 弹出第一个Player的参数
	p1.__proto__ = playerConstructor.prototype;
	const resultObj = playerConstructor.apply(p1,arguments);
    return typeof resultObj !== 'object' ? p1 : resultObj;
}

什么是原型链

当某个对象访问对象内部的某个属性时,如果找到了这个属性,就返回这个属性的值,如果找不到就去访问它的构造函数的原型对象的属性值,如果找到了这个属性就返回这个属性的值,如果找不到就访问Object的原型对象,如果找到了这个属性就返回这个属性的值,否则返回undefined。

Object.prototype.name = 'Object';

function Player() {}

Player.prototype.name = 'Player';

const p1 = new Player();

p1.name = 'p1';

console.log(p1.name); //p1

// 删除p1.name
delete p1.name;

console.log(p1.name); //Player

delete Player.prototype.name;

console.log(p1.name); //Object

继承

1.原型链继承

function Parent(){}

function Child(){}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

缺点:

如果有属性是引用类型的,一旦某个实例修改了这个属性,所有实例都会受到影响

无法传参

2.构造函数继承

function Parent(name) {
	this.name = name;
	this.start = function(){
        console.log(this.name+'start');
    }
}

function child(id,name){
    const args = Array.from(arguments).slice(1)
	Parent.apply(this,args);
    this.id = id;
}

缺点:

每一次调用构造函数,都会再创建一遍方法,占用内存

3.组合继承

function Parent(name) {
	this.name = name;
}
Parent.prototype.start = function(){
    console.log(this.name+'start');
}
function child(id,name){
    const args = Array.from(arguments).slice(1)
	Parent.apply(this,args);
    this.id = id;   
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

缺点:

Parent.appy(this,args)和new Parent()调用了两边构造函数。

4.寄生继承

function Parent(name) {
	this.name = name;
}
Parent.prototype.start = function(){
    console.log(this.name+'start');
}
function child(id,name){
    const args = Array.from(arguments).slice(1)
	Parent.apply(this,args);
    this.id = id;   
}


//方式1
let TempFunction = function(){};
TempFunction.prototype = Parent.prototype;
child.prototype = TempFunction.prototype;
//方式2
Child.prototype = Object.create(Parent.prototype);


Child.prototype.constructor = Child;

上述无法直接用Child.prototype = Parent.prototype,会存在原型对象污染问题

5.class

class Parent{
	constructor(name){
		this.name = name;
	}
	
	start(){
		console.log(this.name+'start');
	}
}

class Child extends Parent{
	constructor(id,name){
		super(name);
		this.id = id;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值