JS原型和原型链

1. 前言

JS中原型和原型链的概念一直都是混淆不清,确实需要时间,偶尔回头看看。对于原型和原型链的理解,其实一直处于比较浅的概念。有句话说,没理解透原型和原型链,就算还没有真正入门的前端。希望通过总结这篇文章,我算的上入门前端了,没入门也能偶尔翻翻看看/(ㄒoㄒ)/~~。

在理解原型之前,需要弄清楚几个概念:函数对象、普通对象、原型对象(prototype)、__proto__属性和构造器constructor。

2. 函数对象

顾名思义,由函数new Function()创建得来的对象都是函数对象。函数对象拥有__proto__属性和prototype属性。

注意:只有函数对象才有prototype属性!

系统内置的函数对象有

Function、Object、Array、Date、String、自定义函数等

//函数对象
function f1(){};  
var f2 = function(){};  

console.log(typeof f1);  //function  
console.log(typeof f2);  //function  
console.log(typeof Object);   //function  
console.log(typeof Array);   //function  
console.log(typeof String);   //function  
console.log(typeof Date);   //function  
console.log(typeof Function);   //function

思考: js的引用数据类型都属于函数对象吗?

3. 普通对象

除函数对象外的对象都是普通对象。且只有指向原型链的__proto__属性,没有prototype属性。

//普通对象  
var a = 123;   
var b = {};         
var c = new Object();   

console.log(typeof a);  //Object  
console.log(typeof b);   //Object  
console.log(typeof c);   //Object  

思考:js有五种基本类型:Undefined,Null,Boolean,Number和String,他们都是属于普通对象吗?

4. 原型对象

JS设计之初为了实现简单继承,引入了prototype属性,也叫原型对象

//原型对象
function animal(){};  

console.log(typeof animal.prototype) //Object  
console.log(typeof Object.prototype) // Object  

从本质上来讲,原型对象是一个普通对象,是函数对象的构造函数创建的一个实例。相当于在person创建的时候,自动创建了一个它的实例,并且把这个实例赋值给了prototype。

但是存在一个特例Function, Function.prototype是原型对象,本质却是函数对象。作为一个函数对象,又没有prototype属性。

console.log(typeof Function.prototype) // 特殊 Function  
console.log(typeof Function.prototype.prototype) //undefined 函数对象却没有prototype属性

这里写图片描述

思考:原型对象prototype 属于函数对象吗?

5. __proto__属性

__proto__属性在本质上为一个指针,指向创造obj对象的函数对象的prototype属性。所有的对象obj都具有proto属性(null和undefined除外)。

这里写图片描述

function Dog(){};  
Dog.prototype.name = "小黄";  
Dog.prototype.age =  13;  
Dog.prototype.getAge = function(){  
    return this.age;  
}

var dog1 = new Dog();  
var dog2 = new Dog();  

dog2.name = "小黑";  
console.log(dog1.name); // 小黄 来自原型  
console.log(dog2.name); // 小黑 来自实例 

对象dog1和对象dog2中的__proto__属性指向创造其实例的函数对象Dog的原型对象即Dog.prototype,如下所示:

dog1.__proto__ === Dog.prototype  //true

Dog.prototype.__proto__ === Object.prototype //继承Object 下面原型链说  

dog1.__proto__.__proto__ === Object.prototype  

Dog.prototype.constructor === Dog   

Dog.prototype.isPrototypeOf(dog1)  

获取对象的原型  
dog1.__proto__  //不推荐  
Object.getPrototypeOf(dog1) === Dog.prototype   //推荐

这里写图片描述

思考一下,var obj={}; obj.prototype.proto指向谁?

6.构造器constructor

constructor 属性返回对创建此对象的函数对象的引用。

function a(){};
console.log(a.constructor===Function); //true
console.log(a.prototype.constructor===a); //true

函数a是由Function创造出来,那么它的constructor指向的Function,a.prototype是由new a()方式创造出来,那么a.prototype.constructor理应指向a

思考:a.prototype.proto.constructor指向谁?

7. 原型链

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数想指针(constructor),而实例对象都包含一个指向原型对象的内部指针(proto)。
如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针(proto),另一个原型也包含着一个指向另一个构造函数的指针(constructor)。
假如另一个原型又是另一个类型的实例……这就构成了实例与原型的链条。

function animal(){  
    this.type = "animal";  
}  
animal.prototype.getType = function(){  
    return this.type;  
}  

function dog(){  
    this.name = "dog";  
}  
dog.prototype = new animal();  

dog.prototype.getName = function(){  
    return this.name;  
}  

var xiaohuang = new dog();
//原型链关系  
xiaohuang.__proto__ === dog.prototype  
dog.prototype.__proto__ === animal.prototype  
animal.prototype.__proto__ === Object.prototype  
Object.prototype.__proto__ === null 

这里写图片描述

8.思考解答

函数对象思考题解答

思考: js的引用数据类型都属于函数对象吗?

引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象

那么数组,普通对象,函数对象都算是引用数据类型,引用数据类型范围包含函数对象的范围

普通对象思考题解答

思考:js有五种基本类型:Undefined,Null,Boolean,Number和String,他们都是属于普通对象吗?

基本类型值:指的是保存在栈内存中的简单数据段;除开函数对象之外的对象都是普通对象,那么普通对象范围是包含基本数据类型的。

事实上(函数对象,普通对象)以及(基本数据类型,引用数据类型)是在不同角度对js变量进行的定义

原型对象思考题解答

思考:原型对象prototype 属于函数对象吗?

事实上 这个问题要进行分别回答:

Function.prototype 属于函数对象,其他对象的prototype属于普通对象

function a(){};
console.log(typeof Function.prototype); // function
console.log(typeof a.prototype); //object

原型对象prototype的创造过程为:

    var temp = new a();
    a.prototype = temp;

temp当然是普通对象,但是看下Function的prototype创造过程:

    var a = new Function();
    Function.prototype = a;

现在不难理解,Function的prototype为什么是函数对象了。

指针_proto_思考题解答

思考一下,var obj={}; obj.prototype.proto指向谁?

这里分步思考:

1、obj是是一个普通对象
2、什么类型的对象是由prototype属性的?当然是函数对象
3、所以obj是没有prototype属性的
4、所以obj.prototype===undefined
5、所以此题的最终问题是:undefined.proto指向什么
6、所有的对象obj都具有proto属性(null和undefined除外)!所以答案是 js报错

构造器constructor思考题解答

思考:a.prototype.proto.constructor指向谁?

function a(){};

这里继续分解题目:

1、a.prototype指向a的一个实例,我们已经多次强调了,而且属于普通对象
2、proto定义为:指向创造obj对象的函数对象的prototype属性,所以看下谁创造了a.prototype,因为a.prototype是普通对象,类型为object,那么是Object创造了它。
3、那么显而易见a.prototype.proto指向了Object.prototype
4、那么题目简化为Object.prototype.constructor指向谁
5、继续分解题目,Object.prototype为基本对象,那么就是Object创造了它,那么它的constructor就指向了Object

Object.prototype.constructor===Object //true

继续之,到了尽头

Object.prototype.__proto__===null //true

参考原文:http://www.0313.name/2017/01/13/prototype-proto-constructor.html

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逸尘️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值