__proto__和prototype属性:

1、__proto__属性:

在JS里,万物皆对象(函数是对象、原型也是对象...)。对象都具有属性__proto__,这个属性会指向该对象的原型。

2、prototype属性:

除此之外,函数(Function)也是对象,而且函数除了上面说的__proto__这个属性外,还有额外的一个prototype属性。函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是下面例子中的 person1 和 person2 的原型。

那什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。

原型链:

1、函数和原型关系:

我们先使用构造函数创建一个对象,Person 就是一个构造函数(注:首字母大写只是约定俗成,不大写照样可以),我们使用 new 创建了两个实例对象 person1和persion2。

function Person() {

}

// prototype是函数才会有的属性
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin

让我们用一张图表示构造函数和实例原型之间的关系:

在这张图中我们用 Object.prototype 表示实例原型。(构造)函数有一个prototype属性,指向了实例原型。

2、实例和原型关系:

那么我们该怎么表示实例与实例原型,也就是 person 和 Person.prototype 之间的关系呢?很自然,我们知道没有对象都有__proto__属性,而且他指向的就是对象的原型。

function Person() {

}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true

3、构造函数:

既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,如下代码可以验证

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

讲到这里,我们知道了函数、对象实例和原型之间的关系了,他们是通过prototype和__proto__两个属性联系起来的。如下图

4、原型链:

原型链就是依托__proto__和prototype连接起来的一个原型链条,我们先看个例子

function Person() {
}
// 原型属性
Person.prototype.name = ‘Jiang’
var person1 = new Person()
// 实例属性
person1.name = ‘J’
console.log(person1.name) // J

上面代码中在实例属性和原型属性都有一个名为name的属性,但是最后输出来的是实例属性上的值。

当我们读取一个属性的时候,如果在实例属性上找到了,就读取它,不会管原型属性上是否还有相同的属性,这其实就是属性屏蔽,即当实例属性和原型属性拥有相同名字的时候,实例属性会屏蔽原型属性,记住只是屏蔽,不会修改,原型属性那个值还在;但是如果在实例属性上没有找到的话,就会在实例的原型上去找,如果原型上还没有,就继续到原型的原型上去找,直到尽头。

这个尽头是啥?由于原型也是对象,所以也会有__proto__属性,也就是原型的原型;最后就可以找到Object.prototype这个大boss,所有原型对象都是Object构造函数生成的(Object.prototype值为null)。正是因为所有的原型最终都会指向Object.prototype,所以对象的很多方法其实都是继承于此,比如toString()、valueOf(),前面用到的hasOwnProperty,甚至是.constructor、proto

补充:一些常用方法:

1)检查对象是否有该属性:

function Person() {
}
var person1 = new Person()
// 实例属性
person1.name = ‘J’
person1.hasOwnProperty(‘name’) // true

注:hasOwnProperty属性只有存在于实例中才会返回true

2)in则会遍历所有属性,不管是实例上的,还是原型上的:

function Person() {
}
Person.prototype.age = ‘100’
var person1 = new Person()
person1.name = ‘J’ 'name' in person1 // true
'age' in person1 // true for (var prop in person1) {
console.log(prop) // name age
}

---------------------
作者:赶路人儿
来源:CSDN
原文:https://blog.csdn.net/liuxiao723846/article/details/81984357

js原型和原型链,以及__proto__、prototype属性的更多相关文章

  1. 对js原型对象、实例化对象及prototype属性的一些见解

    什么是原型对象? 请看下面的代码,我们以各种姿势,创建了几个方法! function fn1() { } var fn2 = function () { } var fn3 = new Functio ...

  2. JavaScript OOP(三):prototype原型对象(即构造函数的prototype属性)

    通过构造函数生成的实例化对象,无法共享属性或方法(即每个实例化对象上都有构造函数中的属性和方法):造成了一定的资源浪费 function Obj(name,age){ this.name=name; ...

  3. JS构造函数内的方法与构造函数prototype属性上方法的对比

    本文的目的是让大家理解什么情况下把函数的方法写在JavaScript的构造函数上,什么时候把方法写在函数的 prototype 属性上;以及这样做的好处. 为了阅读方便,我们约定一下:把方法写在构造函 ...

  4. JavaScript原型和原型链( prototype 与 __proto__ )

    一.函数对象 所有引用类型(函数.数组.对象)都拥有__proto__属性(隐式原型) 所有函数拥有 prototype 属性(显式原型)(仅限函数) 原型对象:拥有 prototype 属性的对象, ...

  5. 总结一下js的原型和原型链

    最近学习了js的面向对象编程,原型和原型链这块是个难点,理解的不是很透彻,这里搜集了一些这方面的资料,以备复习所用 一. 原型与构造函数 Js所有的函数都有一个prototype属性,这个属性引用了一 ...

  6. JS原型、原型链深入理解

    原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 一.初识原 ...

  7. Js 原型,原型链

    原型,原型链 原型:在JavaScript中原型是一个prototype对象,用于表示类型之间的关系. 原型链:JavaScript万物都是对象,对象和对象之间也有关系,并不是孤立存在的.对象之间的继 ...

  8. 理解js中的原型链

    对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 关于原型 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承 ...

  9. 对于js原型和原型链继承的简单理解(第一种,原型链继承)

    原型是js中的难点加重点,也是前端面试官最爱问的问题之一,因为面试官可以通过被面试者对原型的理解.来判断被面试者对js的熟悉程度. 原型的定义 Js所有的函数都有一个prototype属性,这个属性引 ...

  10. js原型,原型链的理解

    1.所有引用类型(函数.数组.对象)都拥有_proto_属性(隐式原型) 2.所有函数拥有prototype属性(显式原型)(仅限函数) 3.原型对象:拥有prototype属性的对象,在定义函数时就 ...

随机推荐

  1. Python sorted 函数

    Python sorted 函数 sorted 可以对所有可迭代的对象进行排序操作,sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作.从新排序列表. sorted 语法: ...

  2. Linux(CentOS)启动时自动执行脚本(rc.local)

    下面说说通过rc.local文件进行开机启动 1.首先创建一个启动脚本,这里以启动docker为例 创建 docker-startup.sh 脚本 #! /bin/bash /usr/bin/mk-d ...

  3. Python进阶(二)

    1.模块和包的概念 python的解决方案是把同名的模块放到不同的包中 1.1,导入模块 要使用一个模块,我们必须首先导入该模块.Python使用import语句导入一个模块.例如,导入系统自带的模块 ...

  4. Java 并发学习总结

    目录 基础篇 进阶篇 并发编程的的三个概念(特性)? JMM(Java 内存模型) volatile 关键字 1. Java 内存模型(为什么要有 volatile) 2. volatile 原理 追 ...

  5. IO流总结---- 字节流 ,字符流, 序列化 ,数据操作流,打印流 , Properties 集合

    笔记内容: 什么是流 字节流 字符流 序列化 数据操作流(操作基本数据类型的流)DataInputStream 打印流 Properties 集合 什么是流: 流是个抽象的概念,是对输入输出设备的抽象 ...

  6. 深入浅出《设计模式》之外观模式(C++)

    前言 模式介绍 外观模式相比较之下比较简单,模式设计中定义是为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口是的这一子系统更加容易使用. 如果不理解呢,简单些说就是外观模式提 ...

  7. Java面向对象之泛型

    主要介绍: 认识泛型 构造方法中使用泛型 设置多个泛型 通配符 泛型接口 泛型方法 泛型数组 一.认识泛型 具体实例如下: package com.huolongluo.newfeatures; /* ...

  8. xcodeinstruments 内存检测

    http://blog.csdn.net/totogo2010/article/details/8233565

  9. 【分布式搜索引擎】Elasticsearch之如何安装Elasticsearch

    在Macos上安装 一.下载安装过程 最新版本下载地址: https://www.elastic.co/cn/downloads/elasticsearch 历史版本下载地址: https://www ...

  10. liteos队列(五)

    1. 概述 队列又称消息队列,是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间.任务能够从队列里面读取消息,当队列中的消息是 ...