js 原型链与原型

原型对象

javascript语言是一种面向对象的语言,它没有"子类"和"父类"的概念,里面所有的数据类型都是对象,如何将这些对象联系起来呢?

Brendan Eich在考虑设计继承机制的时候,参考了C++和JAVA使用new命令,通过调用类的构造函数生成实例的方式,将new命令引入javascript。

C++的写法是:

ClassName *object = new ClassName(param);

Java的写法是:

 Person person = new Person();

  

但是,javascript里面没有“类”这个概念,那么,Brendan Eich决定直接在new后面跟一个构造函数,来生成实例。

构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同。任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象。

下面定义一个构造函数Female:

function Female(name){
     this.name = name;
    this.sex = ‘female‘;
 }

通过new命令来生成一个person实例:

var person1 = new Female("Summer")

这里,构造函数Female就是实例对象person1的原型!!!Female里的this关键字就指的是person1这个对象!

new出来的person1对象此时已经和Female再无联系了!也就是说每一个new出来的实例都有自己的属性和方法的副本,是独立的的!修改其中一个不会影响另一个!

var person1 = new Female("Summer");
var person2 = new Female("Lily");

person2.sex = ‘male‘;

console.log(person1.sex)      // female
console.log(person2.sex)      // male

但是,我们希望构造函数中的sex属性是一个共有属性,那么此时用这样的方法,每个实例中都有一个相同的sex属性,会造成资源极大的浪费!

那么原型对象就即将登场了!Brendan Eich决定给每一个构造函数都设置一个prototype属性,这个属性就指向原型对象。其实原型对象就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在在构造函数里!

那么上面的代码可改写如下:

function Person(name,age){
            this.name = name;
        }
        Person.prototype.sex = ‘female‘;

        var person1 = new Person("Summer");
        var person2 = new Person("Lily");

        console.log(person1.sex)      // female
        console.log(person2.sex)      // female

        Person.prototype.sex = ‘male‘;

        console.log(person1.sex)      // male
        console.log(person2.sex)      // male

可以看出,修改prototype属性会影响它的所有实例的sex的值!!

实例一旦创建出来就会自动引用prototype对象的属性和方法!所以实例对象的属性和方法一般分为两种:一种是自身的,一种是引用自prototype的。

具体实现是这样的:

每当代码读取某个对象的某个属性的时候,都会执行一次搜索。首先从对象实例本身开始,如果在实例中找到了该属性,则返回该属性的值,如果没有找到,则顺着原型链指针向上,到原型对象中去找,如果如果找到就返回该属性值。

这里要提一点,如果为对象实例添加了一个属性与原型中同名,则该属性会屏蔽掉原型中的同名属性,不会去修改它!使用delete可以删除实例中的属性提到delete那要插一句~delete只能删除对象下的属性,不能删除变量和参数!

原型链

事实上,js里完全依靠"原型链"(prototype chain)模式来实现继承。

上面说完原型对象。下面要扒一扒proto、prototype、constructor。

  • proto:事实上就是原型链指针!!
  • prototype:上面说到这个是指向原型对象的
  • constructor:每一个原型对象都包含一个指向构造函数的指针,就是constructor

继承实现方式:

为了实现继承,proto会指向上一层的原型对象,而上一层的结构依然类似,那么就利用proto一直指向Object的原型对象上!Object.prototype.__proto__ = null;表示到达最顶端。如此形成了原型链继承。

下面有个图解非常经典,我自己也手画了一遍去理解,真的非常有效~

image

大致总结一下就是:

1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }

2、Function是作为众多function出来的函数的基类 function Function(){ [ native code ] }

3、构造函数的proto(包括Function.prototype和Object.prototype)都指向Function.prototype

4、原型对象的proto都指向Object.prototype

5、Object.prototype.proto指向null

本文系转载 链接:https://www.jianshu.com/p/f30fa27999e3

原文地址:https://www.cnblogs.com/hilad/p/11411671.html

时间: 2024-11-02 18:49:58

js 原型链与原型的相关文章

从零开始学 Web 之 JS 高级(二)原型链,原型的继承

大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:http://www.cnblogs.com/lvonve/ CSDN:https://blog.csdn.net/lvonve/ 在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目.现在就让我们一起进入 Web 前端学习的冒险之旅吧! 一.原型链 原型链

[javascript]js原型链以及原型链继承

基础的三个要素: 函数 ,函数实例,实例原型. 实例原型相当于 父类, 函数相当于构造函数 举例: class Fn extends Fn.prototype{ } 实例: let f = new Fn(); Fn不能直接加方法或者属性,只能通过Fn.prototype f可以动态添加属性或者方法.如果f添加属性与Fn.prototype里面的一致,则会保留两份,例如下面:Kevin不管你是否"覆盖",它都存在. function Person() { } Person.prototy

Javascript的原型、原型链、原型链继承

原型 在javascript中,原型分有两种:显示原型(prototype)和隐式原型(__proto__). __proto__(隐式原型) JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问.ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf(). prototype(显式原型) 这是函数对象特有的属性.这个属性是一个指针,指向一个对象,这

08.22 javaScript 原型的定义 原型链 获取原型 操作原型的属性 判断原型是自有的还是继承的 各种方法

# 原型 ### 定义 * 每一个对象都有原型 * 原型仍然是一个对象 * 模拟实现面向对象的继承性 ### 原型链 * 对象的原型还有原型 * 对象除了可以使用自有属性还可以继承原型上的属性 ### 获取原型 * 对象.__proto__ * 构造函数.prototype ### 操作原型的属性 * 原型本身就是对象,同操作对象 ### 判断属性是自有的还是原型继承的 * hasOwnProperty() ### ECMA5中创建对象并指定对象的原型 * Object.create(); #

关于原型、原型链和原型继承的理解

# 个人理解 原型: prototype首先是只作用于函数的属性,无法直接用于对象或变量. 每个函数中都自带一个__proto__属性(可以存储继承对象中的prototype属性--- p.__proto__ = Person.prototype). 在实例化对象(构造函数)时,寻找某个属性(如demo中的name属性),在当前属性中无法找到属性,会从xxx.__proto__中进行寻找.若还未找到,会继续向xxx.__proto__.__proto__ 中进行寻找. ** 实例化(创建对象)相

原型链和原型对象-3 (原型链)

1.实例对象的属性,有可能再实例对象上,也有可能是再原型对象上定义的. 2.原型对象也是对象,也有原型对象(原型对象的原型对象),一直找下去就是原型链 3.一直寻找,所有对象的原型都可以找到Object 4.Object也有原型,是null 5.null没有原型 得到 (在获取原型对象的时候,用第三种, 对于方法一,es6标准规定__proto__只在浏览器部署, 对于方法二,xxx.constructor.prototype在手动改变原型对象时,会失效) (constructor是什么,下一章

js的原型链

开篇 之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述.有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解.最近正在读<Javascript高级程序设计>,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明. 我们经常会这么写 function Person () { this.name = 'John'; } var person = new Person(

JS面向对象之继承——原型链

原型对象 每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同.比如在firefox下,每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用. 原型链 由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefi

JS的作用域链与原型链

来一波,好记性不如烂笔头. 这两条链子可是很重要的. 作用域链 当执行一段JS代码(全局代码或函数)时,JS引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加载后会首先创建一个全局的作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成了一条作用域链.每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域.作用域链的作用是用于解析标识符,当函数被创建时(不是执行),会将this.arguments.命名参数和该函数中的所有局部变量