资讯专栏INFORMATION COLUMN

JavaScript之原型与原型链

wuyangchun / 2148人阅读

摘要:个人博客原文地址万物皆对象在中除值类型之外,其他的都是对象,为了说明这点,我们举几个例子我们可以使用来做类型判断除了属于值类型之外,其他都是对象。

个人博客原文地址

万物皆对象

在JavaScript中除值类型之外,其他的都是对象,为了说明这点,我们举几个例子
我们可以使用typeof来做类型判断

typeof a;             // undefined
typeof 1;             // number
typeof "wclimb";      // string
typeof true;          // boolean

typeof function(){};  // function
typeof [];            // object
typeof null;          // object
typeof {};            // object

除了undefinednumberstringboolean属于值类型之外,其他都是对象。你可能要问了,不是还有一个是function吗?要校验他是不是应该对象可以这样做:

var fn = function(){}
fn instanceof Object // true

由上面的例子所示,函数确实是对象,为什么呢?我们看一下下面的例子

function Person(name){
    this.name = name; 
}
var person = new Person("wclimb");
console.log(person) // Person {name: "wclimb"}

由此我们可以得知,对象都是通过函数创建的,这么说你可能又会说不对,你看下面的就不是函数创建的

var person = {name:"wclimb"}

你咋就这么飘呢?我竟无言以对,没错,这是个意外、意外、意外。但是归根结底他还是通过函数创建的

    var person = new Object()
    person.name = "wclimb"

so,现在你只要知道对象是通过函数创建的就可以了,来跟着我读:
第一遍 对象都是通过函数创建的
第二遍 对象都是通过函数创建的
第三遍 对象都是通过函数创建的

构造函数(constructor)
function Person(name){
    this.name = name
}
var person1 = new Person("wclimb 1")
var person2 = new Person("wclimb 2")

上面Person就是一个构造函数,我们通过new的方式创建了一个实例对象person
我们来看看person1和person2的constructor(构造函数)是不是指向Person的

person1.constructor === Person // true
person2.constructor === Person // true
原型(prototype)

在JavaScript中,每定义一个函数都会产生一个prototype(原型)属性,这个属性指向函数的原型对象

function Person(){}
Person.prototype.name = "wclimb"
Person.prototype.age = "24"
Person.prototype.sayAge = function(){
    console.log(this.age)
}
var person = new Person()
person.sayAge(); //  24

那么这个prototype到底是什么呢?跟构造函数有关系吗?

上图就可以反映出他们之间的关系

其实函数的prototype指向函数的原型对象,每个对象都会关联另外一个对象,也就是原型,上面的例子改成:

Person.prototype = {
    name: "wclimb",
    age: 24,
    satAge: function(){
        console.log(this.age)
    }
}
隐式原型(__proto__)

上面我们说到每定义一个函数都会产生一个原型,每个函数它不止有原型,还有一个__proto__(隐式原型)
每个对象都有一个__proto__属性,指向创建该对象函数的prototype,我们可以来试试,还是上面的例子:

function Person(){}
var person = new Person()
person.__proto__ === Person.prototype // true

现在他们的关系图如下

由上图我们可以知道:

Person.prototype.constructor = Person
person.__proto__ = Person.prototype
person.constructor = Person

我们可以看到person.__proto__指向构造函数的原型,那么构造函数的原型即Person__proto__指向哪里呢?
我们知道构造函数其实就是由Function来创建的,由此得出:

Person.__proto__ === Function.prototype

那么构造函数的原型即Person.prototype__proto__指向哪里呢?
原型对象其实是通过Object生成的,自然而然的得出:

Person.prototype.__proto__ === Object.prototype

那么Object.prototype__proto__指向哪里呢?答案是null,最终得到下面的图

抛开这张图,来看看下面几道题

person.__proto__

Person.__proto__

Person.prototype.__proto__

Object.__proto__

Object.prototype.__proto__

解:

每个对象都有一个__proto__属性,指向创建该对象函数的prototype,因为Person是person的构造函数

Person === person.constructortrue,所以:person.__proto__ === Person.prototype

Person构造函数是由Function创建的,所以可以得出Person.__proto__ === Fucntion.prototype

我们上面说过Person.prototype其实是一个对象,而对象是由Object创建的,所以 Person.prototype.__proto__ === Object.prototype

Object对象都是函数创建的,所以Object.__proto__ === Function.prototype

虽然Object.prototype是一个对象但是他的__proto__null

实例和原型

当我们要取一个值的时候,会先从实例中取,如果实例中存在,则取实例的值,如果实例不存在,则会顺着原型里找,直到找到

function Person(){}
Person.prototype.name = "我来自原型"

var person = new Person()
person.name = "我来自实例"
console.log(person.name); // 我来自实例
delete person.name
console.log(person.name)); // 我来自原型

首先person实例中有这个属性,返回我来自实例,然后将它删除之后,会从原型中招,也就是person.__proto__,因为Person.prototype === person.__proto__,所以得到我来自原型

总结

原型和原型链基本已经讲解完,不过还有待完善,如有错误,还望指正

GitHub:wclimb

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96457.html

相关文章

  • 进击JavaScript(四)原型原型

    摘要:每一个由构造函数创建的对象都会默认的连接到该神秘对象上。在构造方法中也具有类似的功能,因此也称其为类实例与对象实例一般是指某一个构造函数创建出来的对象,我们称为构造函数的实例实例就是对象。表示该原型是与什么构造函数联系起来的。 本文您将看到以下内容: 传统构造函数的问题 一些相关概念 认识原型 构造、原型、实例三角结构图 对象的原型链 函数的构造函数Function 一句话说明什么...

    XBaron 评论0 收藏0
  • Javascript重温OOP原型原型

    摘要:在构造函数中的中定义的属性和方法,会被创建的对象所继承下来。从上面的输出结果看出,指向了其构造函数的,而本身也是一个对象,其内部也有属性,其指向的是直到最后指向,这条原型链才结束。和都指向,说明原型链到终止。 prototype原型对象 每个函数都有一个默认的prototype属性,其实际上还是一个对象,如果被用在继承中,姑且叫做原型对象。 在构造函数中的prototype中定义的属性...

    lindroid 评论0 收藏0
  • JavaScript深入原型原型

    摘要:深入系列的第一篇,从原型与原型链开始讲起,如果你想知道构造函数的实例的原型,原型的原型,原型的原型的原型是什么,就来看看这篇文章吧。让我们用一张图表示构造函数和实例原型之间的关系在这张图中我们用表示实例原型。 JavaScript深入系列的第一篇,从原型与原型链开始讲起,如果你想知道构造函数的实例的原型,原型的原型,原型的原型的原型是什么,就来看看这篇文章吧。 构造函数创建对象 我们先...

    Songlcy 评论0 收藏0
  • JavaScript 原型周边

    摘要:除此之外,原型是共享的,如果我们有的写法,改变这两个对象任何一个的原型都会影响另外一个,这在大多的情况下是不可取的。当对象查找一个属性的时候,他会沿着原型链一直往上追踪,直到直到为之。在性能方面,原则上应该尽量避免原型链太长。 简介 如果之间学习过cpp 、java 之类的语言,都会知道他们是可以基于类 class 进行继承的, 在JavaScript 中,并没有类继承这个概念,要实...

    codecook 评论0 收藏0
  • 深入学习js——原型原型

    摘要:我们用一张图表示构造函数和实例原型之间的关系好了构造函数和实例原型之间的关系我们已经梳理清楚了,那我们怎么表示实例与实例原型,也就是或者和之间的关系呢。 开篇: 在Brendan Eich大神为JavaScript设计面向对象系统的时候,借鉴了Self 和Smalltalk这两门基于原型的语言,之所以选择基于原型的面向对象系统,并不是因为时间匆忙,它设计起来相对简单,而是因为从一开始B...

    FingerLiu 评论0 收藏0
  • 深入学习js——原型原型

    摘要:我们用一张图表示构造函数和实例原型之间的关系好了构造函数和实例原型之间的关系我们已经梳理清楚了,那我们怎么表示实例与实例原型,也就是或者和之间的关系呢。 开篇: 在Brendan Eich大神为JavaScript设计面向对象系统的时候,借鉴了Self 和Smalltalk这两门基于原型的语言,之所以选择基于原型的面向对象系统,并不是因为时间匆忙,它设计起来相对简单,而是因为从一开始B...

    xialong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<