javascript 之 原型链(推导过程)
前言:在学这个的时候,听课,画图,查资料,但是越听越糊涂,主要是之前学的没有总结.没有对每个小知识点进行归纳总结.
在了解什么是原型链前,出一个题目,后面会根据这道题来说明什么是原型链.
学习建议:无论学什么知识点:语言的严谨很重要,否则概念混乱就会导致看不懂
function F() { Object.prototype.a = function () { console.log("a()"); }; Function.prototype.b = function () { console.log("b()"); }; }
请问以下分别为什么值.答案在文章最后揭晓.
疑问回答:
1/"函数"和"方法"有区别吗?
function a(){} //这叫函数 var obj={ name:"张三", getName:function(){ //这叫方法 } }
总结:在对象内部的函数叫方法,所以可以不用纠结 叫"函数"还是"方法",统一称为"函数"没错,称为方法也没错,但是还是要严谨一点.
2/什么时候是对象,什么时候是属性,什么时候是函数?
分析:主要看在什么位置.
除了基本数据类型(string,number,boolean,undefined,null),其他的Object, Function(一种特别的对象) Array都是对象
var a={ //a是对象
name:"张三", //name是a的属性
getName:{ //这里的getName 可以说是a的属性,也可以说是a的方法,也可以说是a的函数,也叫对象
return name;
}
}
3/实例是函数吗?
案例:
let F=function();
F.prototype.getName=function(){}
let f=new F();
typeof f //'object'
typeof F //'function'
答:实例是通过构造函数创建出来的对象,所以 实例是对象,而对象不一定是函数. 函数一定是对象.
具体分析:
1\首先我们知道f实例化F后,F.prototype成为了f的对象成员,所以f._proto_=F.prototype
2\定义:每个函数都有一个prototype.
但是实例没有prototype,所以实例不是函数.
3\F是Function的一个实例,而Function是一个函数,它的实例F也是一个函数 请结合第4点和第六点来看 更重要的是第七点
4/对象和原型链 这个太重要了|||太重要了|||太重要了|||
先了解: Object和Function的关系
先有Object.prototype,
然后构造出
Function.prototype
再构造出
Object和Function
(1)Object对象是由Function函数的原型创建的
Object._proto_ === Function.prototype
(2)Object的原型对象指向空
Object.prototype._proto_===null
(3)Function对象是由他自己本身创建的
Function._proto_ === Function.prototype
(4)其他的普通对象最终指向的都是Object
Function.prototype._proto_ === Object.prototype
5.针对第4点,想知道prototype是怎么解释的
1\在JavaScript中,prototype对象是实现面向对象的一个重要机制。
2\每个函数就是一个对象(Function),函数对象都有一个子对象 prototype对象,类是以函数的形式来定义的。prototype表示该函数的原型,也表示一个类的成员的集合。
3\在通过new创建一个类(构造函数)的实例对象的时,prototype 对象的成员都成为实例化对象的成员.(注:请在console中输出第3点的F.prototype)
6.js的内置函数
Object,Number,Boolean, String,Array ,RegExp, Date,Function,Error,Math,Json等都是内置函数,其中Math,Json是以对象形式存在,无需new便可使用
原型是Function.prototype:Object,Number,Boolean, String,Array ,RegExp, Date,Function
原型是Object.prototype: Math,Json.
第七点:为什么var fn=new Function(),function Fn=new Function(){} 有prototype属性呢? 很重要!很重要!很重要!!!
原理:
function Function()
Function也是一个函数对象,也有__proto__属性,既然是函数,那么它一定是被Function创建,所以Function是被自身创建的,所以它的__proto__指向了自身的Prototype:
这个问题的由来: function A(){} var a=new A(){} 注意哦: function b=new Function(){} funbtion c=new b() 以上两种是一样的,都被实例化了,所以A,b都是构造函数
在后续的结论中:普通对象的原型指向的是Object.prototype
分析:按照上面的 a,c都是实例对象,而普通对象都没有prototype,只有_proto_
问题来了:A 是Function的实例,那为什么A拥有prototype呢?
我的理解: Function 和Object都是Function.prototype创建的,参考上面的原理,Function 相当于是 function Function得到的
同理:function F 不就相当于 function Function. 所以: 我们平时写的函数其实都是 Funnction自身创建的.这也就说明了为什么上述问题的原因
第五点:参考:https://baike.baidu.com/item/prototype/14335187?fr=aladdin :标题:js的prototype
第四点参考:https://www.cnblogs.com/panrui1994/p/9396935.html 标题JS:对象与原型
https://zhuanlan.zhihu.com/p/66446619 标题:Object和Function的鸡与蛋的思考
第三点参考:https://blog.csdn.net/qq_36711388/article/details/90346459 标题:实例化的对象没有prototype属性
第三点参考:https://www.cn blogs.com/jtnote/p/5980000.html 标题:函数的各种写法
一.什么是构造函数?
1\构造函数的函数名首字母大写,用来与普通函数区分
2\构造函数通过 new关键字来调用
3\构造函数中的this指向整个构造函数,而普通函数中的this指向window(此处可忽略,后面会补充)
思考:
function a(){} //只有这一行时,a是普通函数 var a1=new a(); //添加这一句代码后,此时a就是构造函数
结论:只有当使用new关键字,或者是大写时,才能确认是构造函数.
二. 原型
现象:
function F(){}
function a(){}
这两个函数都有prototype属性 和 _proto_属性
var f=new F()
var a1 =new a();
这两个实例只有_proto_属性 没有 prototype属性
重点: 原型分为显式原型(prototype) 和 隐式原型(_proto_).
(一):显式原型(prototype)
特点:
1.每个函数function都有一个prototype
分析:实例可以是函数,
2.在定义函数时自动添加的默认值,prototype指向一个空的Object (看分析,还是有问题,需要理解)
如何分析:(请参考"疑问回答"第四点,解释:prototype是对象,对象都有一个隐式原型_proto_,于是这个隐式原型指向为空.
于是想当然以为let f=functon(){} ,这也是定义函数啊,那f.prototype._proto_肯定也是空,结果不是为null. 唯一得到的准确结果是
Object.prototype._proto_ )
3.prototype有一个属性constructor(函数指针), 指向函数对象(后面会讲到constructor的知识)
4.用来查找对象的属性(方法也是属性的一种)
var F=function(){}
(二):隐式原型(_proto_)
特点:
1.每个实例对象都有一个_proto_
这句变更为:每个对象都存在着一个隐藏的属性"_proto_"
2.所有函数的_proto_都是一样的,因为函数都是new Function()构造器产生的.
3.对象(函数)的隐式原型 等价 对应构造函数的显式原型 即:
let F=function(){} let f=new F();
f._proto_ = F.prototype
4.原型链是沿着_proto_查找的
(三):扩展:
在ES6之前,程序员可以直接操作prototype,但是不能操作_proto_的
答案:
理解一下:概念 (注意:请将所有标红的地方看一遍) f.a() f是F的实例,所以f._proto_ === F.prototype ,然后只能找到 F.prototype._proto_===Object.prototype ,这里有一个操作,无论输入啥,都没有找到其他任何对象===Object.prototype 结论:普通对象的原型都指向Object.prototype(原型) f.b() 找不到. f是对象,所以f._proto_ ====F.prototype F.a() F是函数,它对应的构造函数是Function的prototype,那么F._proto_===Function.prototype 然后Function.prototype 是由 Object.prototype创建的,所以Function.prototype._proto_===Object.prototype ,所以能找到,所以能够找到 F.b() F是函数,它对应的构造函数是Function的prototype 所以能够找到
//2021年 11月 5日,又有了新的感悟
提要:
1/每个实例都只有隐式原型
2/普通对象的原型都指向Object.prototype