对象 Object,函数 Function, 原型 prototype,原型链__proto__;如何才能掌握这四者的关系呢。
一 对象。
创建对象的三种方式。
1 var obj1 = new Object();
2 var obj2 = {};
3 但想抽取公共的属性,做一个模板。 通过构造函数创建对象。
function Star(){
this.uname= uname;
this.age = age;
this.sing = function(){
console.log('sing')}
}
var caomei = new Star('caomei',18);
var dashu = new Star('dashu',18);
构造函数1名称需要大写。2 不需要返回。
对象new的过程。
new 在执行的时候干了4件事。
1 内存中创建一个空对象。
2 让this指向这个空对象。
3 构造桉树里面的代码,给新对象添加属性和方法。
4 返回这个新对象。
- 创建一个全新的对象。
- 这个新对象的原型(
Object.getPrototypeOf(target)
)指向构造函数的prototype
。 - 该函数的this会绑定在新创建的对象上。
- 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
- 我们称这个新对象为构造函数的实例。
对象的两个成员。
1 实例成员。构造函数内部。通过内部this添加的成员。uname age sing都是实例成员。
实例成员只能通过实例化的对象来访。不能通过构造函数来访问实例成员!
2 静态成员 在构造函数本身上添加的成员 sex就是构造成员。
Star.sex = ‘man’;
静态成员只能通过构造函数访问。Star.sex;
二 构造函数的原型属性:prototype
为什么要有prototype?
两个实例对象,开辟两个内存空间,存放函数。浪费内存问题。
caomei.sing() !== dashu.sing()
如何节省空间呢?
构造函数 通过原型分配的的函数 是所有对象所共享的!!!
每一个构造函数都有一个 prototpe属性! 每一个构造函数拥有prototype的属性和方法。
作用:我们可以吧那些不变的方法,直接定义在prototype对象上。
Star.prototype.sing = function(){ console.log('sing')};
var ldh = new Star();
var zxy = new Star();
ldh.sing();
三 对象的原型。以及原型链。__proto__。
问题 :ldh对象 并没有 sing方法,哪里来的?
虽然对象ldh身上没有sing,但是对象有__proto__,它指向我们构造函数的原型对象。
Star0是没有sing方法。Star1也没有sing方法,但是Star1的proto是有sing方法的。
本质:__proto__是用来寻找构造函数prototype原型的,这样就可以继承了。
对象的查找规则:(先看自己是否有钱,没有钱找父母要。)
1先看对象身上是否有sing方法。
2 在根据__proto__原型链,去构造函数原型prototype身上查找sing。
4 constructor构造函数。
构造函数prototype原型对象有constructor属性。
这个属性可以指回构造函数的本身。
constructor作用:用于记录该对象引用的哪个构造函数,可以让原型对象重新指向原来的构造函数。
Object.prototype = {sing:function}直接修改prototype属性。会覆盖掉之前的。
Object.prototype.sing; prototype添加属性。
5
上面讲了对象,原型,原型链,原型属性的constructor属性。我们这次把原型链讲懂。
对象Object是哪里来的 。当然是object构造函数构造出来的。
function Object()当然有prototype属性。Object.prototype属性的proto原型是谁呢?当然是null。
function Object()的proto属性指向的是谁呢? 指向的是function.prototype;
function Function() 当然也有prototype属性。 Fcuntion.prototype的proto原型是谁?是Object.prototype。
function Function()的proto属性指向的是谁? 很诧异,是Fcuntion.prototyp。这个是它的底层实现。这个就是最诡异的。一般都是一个三角关系。这个是一个平行关系 。
注意四个对象的__proto__都指向哪里?
两个函数的原型__proto__都是指向 Fcuntion prototype。结论:也就是说构造函数的原型都是Fcuntion prototype。
但是 Object.prototype的 proto指向的null。
但是Function.prototype,和其他构造函数的prototype是指向 Object.prototype。
结论:
当fcuntion Foo(){}的时候。
Foo.__proto__找的是function.prototype。
Foo.prototype找的是object.protptype;
当var foo1 = new Foo的时候;
foo.__proto__找的是Foo.prototype;
在总结一下:
所有构造函数都必须有个prototype属性。这个属性有个constructor 指回去。
找的是翻译成就是原型链。
构造函数的函数(Fun) 找的是 Fcuntion.prototype(它就是用来生产构造函数的)。
构造函数的函数属性(Fun.prototype) 找的是Object.prototype(它是用来生产构造函数的prototype属性)。
构造函数的对象(fun1,fun1) 找的是 构造函数的函数属性Function.prototype(它是用来生产构造函数的对象的。)。
6 js查找机制:(按照原型链的查找机制)
1 再查找对象。2找对象的构造函数。3找对象的构造函数的构造函数。4 在没有了。就是null。
如果第一次查找到成员,那么不在继续查找对象,直接结束。也可以称为就近原则。
在对象自身查找的方法:
object.hasOwnProperty('a');
'a' in object
ES6以后都是类class,但是proto是自己造轮子,和看源码必备的。
几个个博客写的很好:
掘金:
https://juejin.cn/post/6844903989088092174
https://juejin.cn/post/6844904097166917639
https://juejin.cn/post/6844903585336016903
https://juejin.cn/post/6844903924307230727#heading-1
https://juejin.cn/post/6844903806694588424
https://juejin.cn/post/6902282491030470663
知乎:
https://zhuanlan.zhihu.com/p/294808520
csdn:
https://blog.csdn.net/qq_34803821/article/details/85003256
https://blog.csdn.net/qq_34803821/article/details/85003441
https://blog.csdn.net/qq_34803821/article/details/85003539
几个视频也很不错
攻克原型原型链:
https://www.bilibili.com/video/BV1ci4y157Ci?p=6
https://www.bilibili.com/video/BV1KJ411x7X7?p=30 (后盾人)
综合知识:
https://www.bilibili.com/video/BV1KJ411x7X7?p=30 (pink老师)
面试考点:
https://www.bilibili.com/video/BV1ti4y187hg/?spm_id_from=333.788.recommend_more_video.0