前端 js 之 面向对象(原型、原型链及继承) 06

今天又是一个美好的一天耶 ! ✌


一、面向对象


对象:

  • 一组属性的无序集合,由key和value组成(相比数组来说,提升了查找速度和数据传输速度)

  • 如果我们想对某个属性精准的操作控制,可以使用属性描述符 object.defineProperty

  • 创建对象的有两种方式,一种是字面量,一种通过 new 关键字(构造函数)创建

构造函数:

  • 构造函数,又称为构造器,通常是我们创建对象时会调用的函数
  • proto.constructor 浏览器提供的
  • object.getPrototypeOf es5之后官方提供的

二、new 的过程

  1. 在内存中开辟一个新的地址,创建一个新的对象
  2. 这个对象的【prototype】 属性会被赋值为他构造函数的 prototype
  3. 构造函数的this ,会指向创建的新对象
  4. 执行函数
  5. 如果构造器没有返回一个非空对象,就会返回这个新对象

三、原型 ( prototype )

  • js 中每个 对象 都一个内置属性 prototype(proto), 当我们通过引用对象的属性key 来获取一个value值时,他会触发get操作,这个操作会现在自身找是否有对应属性,如果没有就会通过这个内置属性 prototype 指向的对象上找 (这个内置属性只能用来查找)

  • js 中每个函数有一个属性 prototype ,

  • 但我们通过new 的方式创建出来的对象,他的prototype会指向他构造函数的内置属性【prototype】

	function Pro(){

	}
	let obj= new Pro()
	 
	obj={}
	obj.__proto__ = Pro.prototype
	

constructor 属性:

  • 原型对象上有个属性 constrctor , 可以查看当前函数对象的指向
	function Pro(){

	}
	let obj= new Pro()
	
	console.log( obj._proto_.constructor )
	console.log( Pro.prototype.constructor )
	 

答 : js 中每个函数都有一个原型属性 prototype, js 中每个对象都有一个内置原型属性 prototype, 当通过new出来的对象他的内置属性prototype(proto)会指向该构造函数的prototype, 原型的优势就是:可以将公共的函数方法放在原型上,供new出来的对象共享

答 : 如果我们想获取一个对象的某个属性时,会先在本身找,找不到会他的原型上找,因为类似于一个链条,所以把这种查找方式称为原型链,原型链的最顶层的原型对象是 object的原型对象

四、构造函数的优势

  1. 封装: 可以将属性和方法封装到一个类中,这个过程叫做封装
  2. 继承: 通过new构造出来的对象,在执行过程中其实每次都会开辟新的内存空间创建函数执行上下文, 特别费内存,可以将公共的函数方法放在原型上,让所有new出来的对象共享
  3. 多态: 不同对象在执行时表现的不同状态

面向对象设计 OOD

  • 我们在做功能时尽可能将需求拆分成能直接实现的小需求:高内聚,低耦合
  1. 高内聚:一个需求的所有功能和属性必须从属于一个主体(所有的功能和数据,尽可能从属于一个对象)
  2. 低耦合:减低功能之间的关系,每个功能可以独立使用或随时被替换 (功能尽可能拆分,依赖关系降到最低)

五、继承


1. 原型、原型链的继承

  • 通过修改原型链实现继承 ,(假设构造函数一继承了构造函数二)
  • 构造函数一继承的属性在打印时是看不到,因为是继承的是隐式原型 构造函数一new出的对象的proto 指向构造函数二 隐式原型打印时是看不到的
  • 修改引用类型的值会互相影响
  • 构造函数一在实现类的过程中是不能传参的
    构造函数二
    function Parent(msg) {
	  this.msg = msg;
	}
	Parent.prototype.init = function () {
	  console.log("哈哈哈哈");
	};
	
	
	构造函数一
	function Child(msg) {
	
	}

	Child.prototype = new Parent()   // 修改原型链
	Parent.prototype = Child.prototype;  // 修改原型

2. 借用构造函数继承

  • 通过修改 this 指向实现继承
  • 解决了原型原型链继承问题
  • 缺点就是不能继承原型上的属性和方法
	function Parent(msg) {
	  this.msg = msg;
	  this.show = function () {
	    console.log(this.msg);
	  };
	}
	Parent.prototype.init = function () {
	  console.log("哈哈哈哈");
	};

	function Child(msg) {
	  Parent.call(this, msg);
	}
	const C = new Child("hi");
	C.show();   // c 就可以使用p的构造函数内的方法,
	C.init();   // 但是他不能继承原型上的属性和方法   !!! 这就是继承的特点,

3. es6提供的继承方式

  • 语法层面上的继承
  • 但其实就是官方封装了方法
  • 官方封装了 构造函数+ 原型链继承

	// 定义 class 而不是之前的 function,
	// 注意 属性和方法的写法
	// 通过 extends 继承,可以使用 super 传递给被继承的
	// 这是官方封装好的


	class Parent {
	  constructor(msg) {
	    this.msg = msg;
	  }
	  show() {
	    console.log(this.msg);
	  }
	}
	class Child extends Parent {
	  constructor(m) {
	    super(m);
	  }
	}
	const P = new Parent("hello");
	const C = new Child("hi");
	



请添加图片描述

你学废了吗?😂      谢谢阅读,谢谢点赞并关注(没错我就要道德绑架你!)

原型链的弊端:

  1. 直接打印看不到这个属性,因为他的属性是保存在构造函数上的
  2. 这些属性会被多个对象共享,因为对象是一个引用类型,可能会造成问题
  3. 不能给构造函数传参,因为这个对象是一个性创建的(没办法定制化)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值