原型和继承


前端小白学习笔记,如果有什么错误,感谢各位大神的批评指正。。感谢,感谢!!

原型

__proto__和prototype的区别

每个函数function都有一个prototype,即显式原型(属性)
每个实例对象都有一个__proto__,即隐式原型(属性)

  1. __proto__是对象的隐式属性,prototype是对象的显式属性。
  2. 对象的隐式原型的值为其对应构造函数的显示原型的值。
    本质上 原型是一个对象。
    在这里插入图片描述

对象有原型

一般情况下,我们可以认为一个对象的原型就是它的父亲。
当我们创建一个对象时,默认有父亲。
例如 let app = {} app是有原型的,app.__proto__ == Object.prototype 就是他的原型,由于Object.prototype包含了一些方法,例如hasOwnProperty,因此app可以通过app.hasOwnProperty()调用。
就是说 儿子可以使用父亲的钱。

优先调用自身方法

如果自身没有对应方法,原型有,则会调用原型中的方法。

	let son = {}
	son.__proto__.show = function(){
		console.log('我是父亲中的show')
	}
	son.show()  //我是父亲中的show
	//son没有show方法,但是父亲有,因此可以调用父亲中的show方法,
	//即:儿子没有车,但是可以开父亲的车出去浪

//如果儿子也定义了同样的方法

	let son = {show:function(){console.log('我是儿子中的show')}}
	son.__proto__.show = function(){
		console.log('我是父亲中的show')
	}
	son.show()  //我是儿子中的show
	//即:儿子有车,就开自己的车出去浪

创建一个无原型的对象

如何创造一个没有原型的对象(没有父亲的儿子?)

create作用是创建一个对象,第一参数是所创建对象的原型,第二参数是先创建对象的配置。

//完全数据字典对象    没有原型的对象
    let hd = Object.create(null,{
      name: {
        value: '后人'
      }
    });

以上是普通对象的原型,接下来看看函数对象的原型。

函数的原型

默认情况下,一个普通对象只有一个原型,__proto__
但是一个函数对象默认有两个原型,__proto__和 prototype

  1. prototype中的方法是供给实例对象user使用的。即:User.prototype === user.__proto__
	function User(){}
	let user = new User()
	User.prototype === user.proto     //true

当在User的prototype定义一个show方法时,只能由user用,User不可以使用。
同理,在User的__proto__定义一个方法时,只有User用,user不可以用

User.prototype.show = function(){console.log('123')}
User.__proto__.show = function(){console.log('456')}
user.show();   //123
User.show();   //456

函数的原型和Object的关系

在这里插入图片描述
obj可以看做是由Object创建的实例对象,因此obj.__proto__ === Object.prototype
同理可得:
  arr.__proto__ === Array.prototype
  str.__proto__ === String.prototype
  bool.__proto__ === Boolean.prototype
为什么原型的父亲是 Object 呢?
因为原型也是一个对象,对象的父亲不就是Object嘛?

原型的查看和修改

使用 Object.setPrototypeOfObject.getPrototypeOf 修改和查看原型

Object.setPrototypeOf(hd,parent)   //设置hd的原型为parent
Object.getPrototypeOf(hd)		   //查看hd的原型

constructor

  prototype指向原型(父亲),constructor指向 指向原型的对象(儿子)
例如:

User.prototype.constructor == User
user.__proto__.constructor == User

如果我们想给原型添加方法

User.prototype.show = function(){};  //没有修改原型
User.prototype = {         //这种方法修改了原型,
	constructor:User       //因此还需要配置默认的指针  constructor
	show(){};    
}

通过一个实例对象创建相同构造函数的其他实例。
即:通过儿子创建他的兄弟姐妹

//初始化构造函数
    function User(name){
      this.name = name
    }
    User.prototype.show = function(){
      console.log(this.name)
    }
    let user = new User('xiaohan')
    //通过user创建一个user2
    //1.创建函数createByObject
    function createByObject(obj, ...args){
      //2.找到obj对应的构造函数User
      let constructor = Object.getPrototypeOf(obj).constructor
      //创建新实例对象
      let obj2 = new constructor(...args)
      return obj2
    }
    let user2 = createByObject(user,'haomi')

instanceof

检测 a 的原型链上有没有A的构造函数对应的prototype

a instanceOf A

代码演示:instanceof 用法

	//先创建一个A的构造函数及实例化对象
	function A(){}
	let a = new A();
	//在创建一个B 的构造函数及实例化对象
	function B(){}
	let b = new B();
	//接下来,把b作为A的原型
	A.prototype = b 
	console.log(a instanceof B)   //false  ?
	console.log(a instanceof A)   //false  ???  
	console.log(a instanceof Object)   //true    此时a的原型链上只有Object
	console.dir(Object.get)
	
	let aa = new A()
	console.log(aa instanceof B)   //ture
	console.log(aa instanceof A)   //true

为什么a对应的两个是false?
  对比a 和 aa ,应该 先改变A.prototype,再创建实例对象
在这里插入图片描述

isPrototypeOf

  判断a是否是b原型链上的一份子 a.isPrototypeOf(b)
  区别:isPrototypeOf是直接判断两个对象的关系;
          instanceof是判断一个对象和一个构造函数的原型的关系

    let a = {}
    let b = {}
    //判断对象b是否是对象a的原型链上的一份子
    console.log(b.isPrototypeOf(a))  //false
    console.log(Object.isPrototypeOf(a)) //false
    console.log(Object.prototype.isPrototypeOf(a)) //true
    console.log(b.__proto__.isPrototypeOf(a)) //true
    Object.setPrototypeOf(a,b)
    console.log(b.isPrototypeOf(a)) //true

hasOwnProperty

 检测属性是否存在
in 可以检测自身和原型链,但是hasOwnProperty只能检测自身属性

 let a = {name : '123'};
 let b = {url : '12321'};
 Object.setPrototypeOf(a,b)
 console.log('name' in a) //true
 console.log('url' in a) //true
 console.log(a.hasOwnProperty('name')) //true
 console.log(a.hasOwnProperty('url')) //false

this

在原型中,this永远指向调用的对象。

继承

改变构造函数的继承错误

function User(){}
User.prototype.show = function(){console.log('123')};
//接下来定义另一个实例对象,并让他继承User的方法
function Admin(){}
Admin.prototype.view= function(){console.log('456')};
Admin.prototype = User.prototype
let ad = new Admin;
ad.show()
ad.view()  //Uncaught TypeError: ad.view is not a function

此时ad使用的是User的prototype,丢失了view方法。
在这里插入图片描述
改变构造函数的继承可以理解为:儿子为了继承父亲的遗产,把自己已有的钱全扔了。

原型的继承

不要让Admin直接继承,而是让它的原型去继承

Admin.prototype.\_\_proto\_\_ = User.prototype

在这里插入图片描述
此时Admin可以同时使用两种原型的方法。
第一种方法是Admin换了个爸爸,第二种方法是爸爸给Admin找了个爷爷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值