从__proto__属性说起
我们都知道,javascript创建对象一般有两种方式:
方式一:通过字面量创建,例如:
var obj = {} //创建一个空对象
var obj1 = { name :'js'} //创建带属性的对象
方式二:通过new关键字,如:
//内置构造函数
var numObj = new Number(3) //创建一个number对象
//自定义构造函数
function Myobj (){
this.name = 'obj'
}
var mObj = new Myobj()
说明:
通过字面量创建对象,其实是内部隐式的通过new Object()创建,所以从根本上说,所有js对象一般都通过new 构造函数() 的形式创建。
我们把上面的函数在控制台打印,展开后属性如下:
会发现,每一个对象展开其属性后都会有一个__proto__的属性,这个属性指的就是该对象的原型的引用,你可以通过该属性来查看该对象的构造函数的原型,并能通过该属性增删改该对象原型的属性。
什么是构造函数
和字面意思一样,就是创建该对象的那个函数。
如何查看该对象的构造函数?
__proto__属性下的constructor属性指的就是该对象的构造函数,既可以查看是哪个函数把这个对象创造出来的。
对象的祖先:原型
原型是所有构造函数中,一个叫prototype属性,他的值类型是一个对象。通过该构造函数创建的对象,都会继承prototype中的属性。
Object.prototype.height = '180cm'
Object.prototype.name = 'i am Object'
var obj = {}
Number.prototype.name = 'i am Number'
var numObj = new Number(3)
var numObj1 = new Number(4)
Myobj.prototype.age = 18
function Myobj (){
this.name = 'obj'
}
var mObj = new Myobj ()
var mObj1 = new Myobj ()
在控制台查看一下属性:
即使自身没有的属性,只有构造函数的原型上有,对象都会拥有该对象。
原型链
基于上面的代码,在控制台打印如下例子:
为什么numObj ,numObj1 ,mObj ,mObj1这几个对象也会拥有height属性呢?
以mObj为例,我们在控制台展开其属性:
发现,所有构造函数的最终的祖先一般都是Object(),所有其实原型会继承Object函数的原型,因此在这种继承关系中形成一种链式的继承关系,这种原型的链式继承结构就是原型链。
当自身没有的属性,会沿着原型链上查找,mobj没有height属性,但是通过原型链,可以从构造函数object的原型上找到,也可以理解成,mobj继承了原型链上的height属性。
另外一种创建对象的方法:Object.creat(对象|null)
Object.create()方法仅能填对象或者null,区别就是:若填入的参数为对象时,创建出来的对象的原型为该参数。若填入的参数是null,创建出来的对象无原型。
var myObj = Object.create({name:'js'})
var nullObj = Object.create(null)
在控制台输出结果: