原型和原型链-JavaScript

原型和原型链

原型:每个对象都有原型对象。
原型链:原型对象也可能拥有原型,一层接着一层,并从其中继承方法和属性。

此外:

1⃣️:每个 实例对象 都有 __proto__ 来访问原型对象。
2⃣️:每个 构造函数 都有 prototype 来访问原型对象。
3⃣️:并且该 实例对象__proto__ == 该 构造函数prototype
4⃣️:查找属性时,实例对象 会依次查找继承的原型对象属性。
5⃣️:大部分 js 对象都是位于原型链顶端的 Object 的实例。

听着比较抽象:

        function a(){

        }
        let b = new a();

这里的 a 就代表 构造函数
这里的 b 就代表 实例对象

原型对象
        let ad = {
            name: "hello world"
        };
        ad.toString();

想象一下,我们并没有为对象 ad 设置 toString() 方法,那么它从哪里获取该方法并调用它的呢?

调用对象 ad 的 __proto__ 方法:

		console.log(ad.__proto__);

输出:

	{
		constructor: ƒ Object()
		hasOwnProperty: ƒ hasOwnProperty()
		isPrototypeOf: ƒ isPrototypeOf()
		propertyIsEnumerable: ƒ propertyIsEnumerable()
		toLocaleString: ƒ toLocaleString()
		toString: ƒ toString()
		valueOf: ƒ valueOf()
		__defineGetter__: ƒ __defineGetter__()
		__defineSetter__: ƒ __defineSetter__()
		__lookupGetter__: ƒ __lookupGetter__()
		__lookupSetter__: ƒ __lookupSetter__()
		get __proto__: ƒ __proto__()
		set __proto__: ƒ __proto__()
	}

可以看到对象 ad 的原型对象中包含了 toString() 方法。

首先,浏览器将在当前对象中查找 toString() 方法。如果找不到,它将调用ad .__ proto__方法来检查是否包含该方法。如果没有,就继续调用ad .__ proto__ .__ proto__方法搜索,依此类推,直到查询的 .__ proto__为空为止。

属性查找

创建构造函数 aa,并为其原型对象设置 age=20。

        function aa(){
            this.name = "anny"
        }
        aa.prototype.age = 20;
        let bb = new aa();
        console.log(bb.name);
        console.log(bb.age);

输出:

anny
20

首先,浏览器查找实例对象 bb 中是否含有 name 属性,有,则显示出来。接着查找实例对象 bb 中是否含有 age 属性,没有,则调用 bb.__proto__ 查找是否含有 age 属性,有,age=20,显示出来。

打印看一下 bb 原型对象的结构(console.log(bb.__proto__)):

	{
		age: 20
		constructor: ƒ aa()
		__proto__: Object
	}
属性遮蔽

为构造函数 aa 设置 age = 23,

        function aa(){
            this.age = 23
        }
        aa.prototype.age = 20;
        let bb = new aa();
        console.log(bb.age);

输出:

23

可以发现原型age的值未展示出来,当在自身属性查找到该属性后,就不会再去原型对象中搜索了,这种情况称之为“属性遮蔽”。

prototype 和 proto

实例对象的 __proto__ 总是指向构造函数的 prototype

bb.__proto__ == aa.prototype

onsole.log(bb.__proto__ == aa.prototype)

输出:

true

当前使用的是通过实例对象来自动寻找构造函数中不存在且搜索继承原型对象中的属性。

如果是构造函数呢。

构造函数查找原型对象

为构造函数创建 name 属性,原型对象设置属性 age。

       function aa(){
            this.name = "anny";
        }
        aa.prototype.age = 20;
        console.log(aa.name);
        console.log(aa.age);

输出:

aa
undefined

为什么 aa.name 没有输出 “anny”?

直接调用构造函数的 name 属性,会返回 构造函数的 函数名称。

另外:

aa.prototype.constructor.name == aa.name

其中:

aa.prototype.constructor 返回的是该构造函数

ƒ aa(){
            this.name = "anny";

        }

那如果非要获取 aa 函数中的 name 属性呢:

通过 new 创建函数 aa 的实例对象 bb,直接访问即可,赋值当然也是如此,bb.name = “XXXX” 。

        let bb = new aa();
        console.log(bb.name);

输出:anny

为什么 aa.age 没有输出 20 呢?

不是说当前对象中没有该 属性,就自动通过 .__proto__ 去寻找吗?

实例对象确实会这么做,但构造函数却不会自动调用其 prototype 方法往上层寻找。

如果想要实现自动寻找原型对象中的属性,就通过 new 创建实例对象来实现。

除了使用 实例对象 的 .__proto__ 方法,也可以使用 Object.getPrototypeOf() 来查找原型对象。

console.log(Object.getPrototypeOf(bb))

或:

console.log(Object.getPrototypeOf(new aa()))

注意前后的关系,传入的参数为构造函数的实例对象。

总结:

创建构造函数 aa 和实例对象 bb:

        function aa(){
            this.name = "anny";
        }
        let bb = new aa();

创建原型对象属性(使用prototype):

		aa.prototype.age = 20;
		aa.prototype.speak = function(){
            alert("hello world");
        }

查找原型对象(两种方法指向同一原型对象且相等):


console.log(aa.prototype);
------------or-------------
console.log(bb.__proto__);

查找属性值:


console.log(bb.name);
console.log(bb.age);
bb.speak();
-----------or--------------
console.log(aa.prototype.age)
aa.prototype.speak()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一拖再拖 一拖再拖

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

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

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

打赏作者

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

抵扣说明:

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

余额充值