原型对象prototype、对象原型__proto、原型链

我们一步步的了解到整个原型链过程:
我们来看一个例子:

function Star(name,age) {
	this.name = name;
	this.age = age;
	this.sing = function() {
		console.log("我会唱歌");
	}
}
var ldh = new Star("刘德华", 18);
var zxy = new Star("张学友", 18);
console.log(ldh.sing === zxy.sing); //false
console.log(ldh.age === zxy.age); //true

因为我们知道函数是一个引用型数据类型,它会单独开辟一个空间存放。
故它们的地址不同,结果就会返回false了,我们再看18是一个简单数据类型,它会存放在一个可以说是常量池的地方,我们创建一次对象,它就会存在,当我们再次创建一次对象时,它直接拿去常量池中的18,故它们相等。
有没有什么办法让ldh.sing === zxy.sing返回true呢?
这时引出了构造函数原型prototype是函数独有的,在JavaScript中,我们创建一个函数A,那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象(即:prototype的属性的值是这个对象 )。这个对象B就称作是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性constructor指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。
此时我们改进程序:

Star.prototype.sing = function() {
	console.log("我会唱歌");
}
console.log(ldh.sing === zxy.sing) //true
ldh.sing();
zxy.sing();

结果返回true是因为我们在这个Star构造函数的原型对象上加了方法,当我们去访问时,由于继承,无论时ldh还是zxy都会访问到sing这个方法,此时,由于访问地址一样,结果就会返回true了。
一般情况,我们的公共属性定义到构造函数里面,公共的方法放在原型对象上。
这里我们会想为什么可以用ldh.sing()调用方法呢?
此时我们又引出了一个属性:对象原型__proto__
对象都会有一个属性__proto__指向构造函数的prototype对象,正是因为它的存在,我们才能直接用ldh.sing()访问原型上的方法啦!
来我们打印一下这个语句,也许就明白了:

console.log(ldh.__proto === Star.prototype); //true

这里我们得知道:对象原型(proto)和原型对象(prototype)都有一个属性constructor(构造函数)
通过:

console.log(Star.prototype.constructor); // f Star(){}
console.log(ldh.__proto__.constructor); // f Star(){}

知道,它们都指向最初的构造函数(Star)本身

在这里我们需要知道方法的查找规则:

  1. 看实例化对象(new 出来的对象,这里指ldh)是否有sing方法,若有,则执行。
  2. 若没有,由于__proto__的存在,它会去构造函数原型对象prototype身上查找sing这个方法。
    注意:
    对象原型只能用实例化对象调用;
    原型对象只能用构造函数调用

    我简单就这个例子画了一个三角型关系图:
    在这里插入图片描述
    这其实也是一个简单版的原型链,复杂的原型链还要涉及到函数(Function),以及Object,我相信上面的三角关系能理清,下面复杂版的也能看懂。
    在这里插入图片描述
    1. __proto__constructor属性是对象所独有的;
      prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__constructor属性
    2. __proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链
    3. prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype。
      constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function

大家可以参考这篇博客,写得非常好,每次看都会受益多多,最后的结论出此:https://blog.csdn.net/cc18868876837/article/details/81211729

猜你喜欢

转载自blog.csdn.net/qq_48784569/article/details/107523260