js原型对象和原型链之间的层级关系
原型对象层级
javaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
案例一
在B站看到了一个很好的JavaScript原型链的视频,看完后把里面的案例改了改写了下来,里面加了一些自己的见解和实践步骤
B站视频地址:https://www.bilibili.com/video/BV1N7411k7D2?from=search&seid=10380415292130567182
//supermarket 超级市场
function supermarket(){};
supermarket.prototype.goods = "洗衣机";
//shop 商店
function shop(){};
shop原型链继承supermarket原型链,也可以理解把商店(shop)理解为分经销商,把超级市场(supermarket)理解为总经销商,分经销商所有的货都是从总经销商那里拿到的
shop.prototype = new supermarket();
这个时候有一个人,需要洗衣机洗衣服,但是自己家里没有洗衣机,这个时候他就去商店买洗衣机,结果到了商店,老板告诉他,他们店里卖的没有洗衣机,但是告诉这个人超级市场卖的有,于是这个人去了超级市场终于买到了洗衣机
//person 人
var person = new shop();
console.log(person.goods); //洗衣机
总结:上面的案例就和原型链原理是一样的,一环扣一环,当我们调用person.goods的时候,实例会查看shop原型对象有没有goods这属性,查看shop原型对象后发现没有goods这个属性,但是shop原型对象成为了supermarket的实例,因此就可以继续往上找也就是supermarket原型对象,当找到supermarket原型对象后查看后发现supermarket原型对象刚好设置了goods这个属性,然后就可以返回supermarket原型对象这个结果了。
但是如果这样写shop.prototype.goods = new supermarket();
console.log(person.goods); //就会打印supermarket
或者 shop.prototype.goods = "哈哈"
console.log(person.goods); //哈哈
这也依了原型链的依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾(到达原型链末尾后如果没有找到匹配的属性则会输出undefined)
案例二
下面是我根据js基础数据类型和引用数据类型的层级关系写的一个案例
js基本数据类型(按值访问):String、number、Boolean 、null(空)、undefined(未定义)
js引用数据类型(按引用访问):Array、function、object
按值访问和按引用访问 参考:https://blog.csdn.net/u014682746/article/details/104991631
{}和[]的区别 {}为js对象、[]为Array数组
这里的声明foo没有用到,声明foo主要为了{}和[]区别,因为我发现很多人也喜欢把foo这种对象也称之为数组
虽然{}和[]同时用的时候确实可以称之为对象数组(如下图struct对象),但是从原则来说struct的类型是属于js对象的 typeof struct 输出 object
var foo = {}; //js对象 object类型 typeof foo 输出 object ; foo instance Array 输出为 false(假)
var arr = []; //Array数组 也属于object类型 typeof arr 输出 object; foo instance Array 输出为 true(真)
var F = function(){}; //function函数 属于function函数和object对象 typeof F 输出 function
Object.prototype.one = function (){return 'Object对象'}; //为object原型上添加one属性
Function.prototype.two = function (){return 'function函数'}; //为function原型上添加two属性
new一个新对象(实例化对象为f,object类型)
function引用数据类型变为object引用数据类型(因为F为function引用数据类型,但是f经过new实例后变为了object引用数据类型)
提示:不管是数组类型(Array)、字符串类型(String)、数字类型(number)、null、Undefined、布尔类型(Boolean),new实例后接收的name都是object类型
var f = new F() ;
//arr Array数组;F function函数;f object对象
console.log(arr.one) //返回object原型上的属性,打印function(){return 'Object对象'}
console.log(arr.two) //Array数组 打印undefined
console.log(F.one) //返回object原型上的属性,打印function(){return 'Object对象'}
console.log(F.two) //返回Function原型上的属性,打印function(){return 'function函数'}
console.log(f.one) //返回object原型上的属性,打印function(){return 'Object对象'}
console.log(f.two) //返回undefined 因为object不属于function,所以object上原型上没有设置two属性也访问不到function原型上的属性,反之function属于object所以通过function原型能访问object原型的属性
Array.prototype.one = function (){return 'Array数组'}; //为Array原型上添加one属性
在这里arr.one 之所以没有在输出object的原型链 是因为arr是属于Array数组 在Array原型链没有创建的前,arr数组在层层向上搜索的过程搜不到arr的上级Array原型,才会去找Array原型的上级object原型,但是如果foo数组找到了Array原型后就会直接引用Array声明的原型对象停止继续向上寻找
console.log(arr.one) //返回Array原型链,打印function(){return 'Array数组'}
这一篇文章能帮助大家理解原型链层级的关系,如果大家想要更深入的了解原型链,可以把构造函数模式和原型模式了解清楚,那个时候你在去看原型链就一目了然,最后希望这篇文章能帮助大家,谢谢大家的观看。