5-13-原型、原型链(学习笔记)

		function Person() {}
		
        Person.prototype.name = '我是人类'

        function Xiaoming() {
            this.name = "我叫小明"
        }
        Xiaoming.prototype = new Person()

        p = new Xiaoming()
        console.log(p);  //Xiaoming{}
        res = p.__proto__;
        console.log('1');
        console.log(res); //Person{} 对象

        res = p.__proto__.__proto__;
        console.log('2');
        console.log(res);  //{name:"我是人类"}

        res = p.__proto__.__proto__.__proto__;
        console.log('3');
        console.log(res);  //{}

        res = p.__proto__.__proto__.__proto__.__proto__;
        console.log('4');
        console.log(res);  //null

        console.log('====================');


        console.log(Xiaoming.prototype);  //Person{}

运行结果:在这里插入图片描述
原型链图:
在这里插入图片描述

上述例子为原型及原型链的实例。

原型链和原型

Constructor 构造函数
首先创建构造函数Person,为区别于普通函要求首字母大写

function Person() {}

prototype 原型
每一个函数都有一个prototype属性,prototype属性指向一个对象。
在这里插入图片描述
这个对象正是调用该构造函数而创建的实例原型
(Person.prototype.name是调用构造函数 Person 而创建的实例 person1、person2 的 原型)

function Person() {}
Person.prototype.name = '人类';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // 人类
console.log(person2.name) // 人类

在这里插入图片描述

每个JavaScript对象(null除外)在创建的时候都会有与之关联的另一个对象,这个对象就是我们所说的原型,每个对象都会从原型“继承”(通过委托访问)属性。

构造函数和原型实例之间的关系
在这里插入图片描述

instance 实例
有个构造函数,我们就可以在原型上创建可以“继承”的属性,并通过 new 操作符创建实例

function Person() {}
        Person.prototype.name = '我是人类'

        xiaoming = new Person()

在这里插入图片描述

proto
每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。
实例Xiaoming.proto 指向 Person.prototype。

console.log(xiaoming.__proto__ === Person.prototype);

在这里插入图片描述

constructor 构造函数
原型通过constructor函数访问到构造函数。

console.log(Person === Person.prototype.constructor); // true

在这里插入图片描述

实例、构造函数、原型
在这里插入图片描述
实例与原型

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型

function Person() {}

        Person.prototype.name = '我是人';

        var xiaoming = new Person();

        xiaoming.name = '我是小明';
        console.log(xiaoming.name) // 我是小明

        delete xiaoming.name;
        console.log(xiaoming.name) // 我是人

当删除实例的属性时,它会向实例的原型查找,通过__proto__。
也就是创造这个实例的构造函数的原型,如果还没有会向原型的原型查找,直至null

原型的原型
原型对象通过Object构造函数生成,实例的__proto__指向构造函数的prototype,
在这里插入图片描述
原型链
原型通过__proto__访问原型的原型。

当访问p中的一个非自有属性,通过__proto__连接起来一系列原型、原型的原型、原型的原型的原型直到Object构造函数为止。
在这里插入图片描述

补充

console.log(p.constructor === Xiaoming.prototype.constructor);
console.log(Xiaoming.prototype.constructor);  //ƒ Person() {}

在这里插入图片描述
proto

大多数浏览器支持这个非标准的方法访问原型,但它并不存在于Person.prototype中,来自Object.pertotype,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.proto 时,可以理解成返回了 Object.getPrototypeOf(obj)。

三句话解释原型和原型链
第一句话:prototype是函数的原型对象,即prototype是一个对象,它会被对应的__proto__引用。
第二句话:要知道自己的__proto__引用了哪个prototype,只需要看看是哪个构造函数构造了你,那你的__proto__就是那个构造函数的prototype。
第三句话:所有的构造函数的原型链最后都会引用Object构造函数的原型,即可以理解Object构造函数的原型是所有原型链的最底层,即Object.prototype.__proto===null
作者:宣泽彬
链接:https://www.jianshu.com/p/7119f0ab67c0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

构造函数的所有实例都可以访问构造函数原型中的方法和属性。
也就是把共有的东西统一存放到一个共享空间。这样可以避免相同函数重复声明,减少空间占用,节省内存。

举个例子:

function Person() {}
        Person.prototype.name = '我是人类'
        console.log(Person.prototype);

        function Xiaoming() {
            this.name = "我叫小明"
        }
        Xiaoming.prototype = new Person()


        let p = new Xiaoming()
        console.log(p); //Xiaoming{}


        console.log(Xiaoming.prototype.constructor); //ƒ Person() {}
        console.log(Person);
        console.log(p.constructor === Xiaoming.prototype.constructor);

        res = p.__proto__;
        console.log('1');
        console.log(res); //Person{} 对象

        res = p.__proto__.__proto__;
        console.log('2');
        console.log(res); //{name:"我是人类"}

        res = p.__proto__.__proto__.__proto__;
        console.log('3');
        console.log(res); //{}

        res = p.__proto__.__proto__.__proto__.__proto__;
        console.log('4');
        console.log(res); //null

        console.log('====================');


        console.log(Xiaoming.prototype.c); //Person{}
        console.log(Xiaoming);
        console.log(Xiaoming.prototype.constructor);
        console.log(Xiaoming === Xiaoming.prototype.constructor);

在这里插入图片描述

		function Person() {}
        Person.prototype.name = '我是人类'

        function Xiaoming() {}
		Xiaoming.prototype = new Person()
        console.log(Xiaoming.prototype.__proto__);
        console.log(Xiaoming.prototype);

        let p = new Xiaoming()

        console.log(p.id);
        console.log(p.name);
        console.log(p); //Xiaoming{}
        res = p.__proto__;
        console.log('1');
        console.log(res); //Person{} 对象
        console.log(Xiaoming.prototype);
        console.log(Person);

        res = p.__proto__.__proto__;
        console.log('2');
        console.log(res); //{name:"我是人类"}
        console.log(Xiaoming.prototype.__proto__);
        console.log(Person.prototype);

        res = p.__proto__.__proto__.__proto__;
        console.log('3');
        console.log(res); //{}

        res = p.__proto__.__proto__.__proto__.__proto__;
        console.log('4');
        console.log(res); //null

在这里插入图片描述
原型链图:
在这里插入图片描述
参考文章:

JavaScript深入之从原型到原型链
🍭 图解原型和原型链

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值