JavaScript之原型与原型链
万物皆对象
在JavaScript中除值类型之外,其他的都是对象,为了说明这点,我们举几个例子
我们可以使用typeof
来做类型判断
typeof a; // undefined typeof 1; // number typeof 'wclimb'; // string typeof true; // boolean typeof function(){}; // function typeof []; // object typeof null; // object typeof {}; // object
除了undefined
、number
、string
、boolean
属于值类型之外,其他都是对象。你可能要问了,不是还有一个是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.constructor
为true
,所以: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
相关推荐
-
关于一个问题 为什么外层套一个立即执行函数 javascript/jquery
2019-9-7
-
前端算法题目解析(一) javascript/jquery
2020-5-26
-
前端构建:3类13种热门工具的选型参考 javascript/jquery
2018-11-30
-
Extjs checkbox数值回显 javascript/jquery
2019-9-17
-
为精美,FButton&FSwitch javascript/jquery
2020-6-12
-
vant IndexBar实现的城市列表 javascript/jquery
2020-5-28
-
vue v-html 小sao操作 javascript/jquery
2020-6-11
-
AngularJS 使用$sce控制代码安全检查 javascript/jquery
2020-6-12
-
jQuery源码分析(五): 拓展接口extend javascript/jquery
2019-7-21
-
前端工程化之路(1)- 使用 verdaccio 搭建私有npm库 javascript/jquery
2020-6-11