1.原型和原型链的概念
js在创建一个对象时,比如叫 obj
,都会给他偷偷的加上一个引用,这个引用指向的是一个对象,比如叫 yuanxing
,
这个对象可以给引用它的对象提供属性共享
,比如:yuanxing
上有个属性name,可以被 obj.name
访问到,
这个可以提供属性共享的对象,就称为前面对象的原型
而原型本身也是一个对象,所以它也会有一个自己的原型,这一层一层的延续下去,直到最后指向 null,这就形成的 原型链
那js的这一种是原型机制是怎么实现的呢?
2.原型的实现
我们先从一个例子来看:
//code-01
let obj = new Object({
name:'xiaomin'})
console.log(obj.name)
console.log(obj.toString())
// xiaomin
// [object Object]
我们首先创建了一个对象obj
,它有一个属性name
属性name
是我们创建的,但是在创建obj
的时候,并没有给它创建toString
属性,为什么obj.toString()
可以访问的到呢?
prototype 属性
我们先来看一下Object.prototype
属性
我们发现这里有toString
属性,所以其实Object.prototype
就是obj
的原型,按照原型的概念,它能够为obj
提供属性共享
所以当obj.toString()
的时候,先在obj
的属性里找,没找到,就在obj
的原型Object.prototype
的属性上找,可以找到,所以调用成功
proto 属性
那么obj
是怎么找到原型的呢?我们打印obj
属性看一下:
我们发现obj
除了我们创建的name
以外,还有一个__proto__
属性,它的值是一个对象,那么它等于什么呢?
我们发现obj.__proto__
指向的就是Object.prototype
到此为止,我们可以简单总结一下js语言实现原型的基本机制了
- 在创建一个对象
obj
时,会给它加上一个__proto__
属性__proto__
属性 指向obj
的构造函数
的prototype
对象- 当访问
obj
的某个属性时,会先在它自己的属性上找,如果没找到,就在它的原型
(其实就是__proto__
指向的对象)的属性上找
构造函数
这个有一个构造函数
的概念,其实构造函数
也就是普通函数,当这个函数被用来 new
一个新对象时,它就被称为新对象的 构造函数
就上面的例子而言,Objec
就是obj
的构造函数,
这里要区别一下Object
和object
的区别,前者是一个js内置的一个函数,后者是js的基本数据类型(number,string,function,object,undefined)
3.new 实际上做了什么
上面有说到new
关键字,那么在它实际上做了什么呢?
上面代码code-01
使用系统内置的函数Object
来创建对象的,那么我们现在用自己创建的函数来创建一个新对象看看:
//code-02
function human(name){
this.name = name
}
human.prototype.say = function(){
alert('我叫'+this.name)
}
let xiaomin = new human('xiaoming')
console.log(xiaomin.name)
xiaomin.say()
这里的human
就是新对象xiaoming
的构造函数
我们把新创建的对象xiaoming
打印出来看看:
我们看到xiaoming
有一个属性name
,并且xiaoming.__proto__
完全等于构造函数的human.prototype
,这就是它的原型
从这里我们可以总结一下new
的基本功能:
- 把
构造函数
的this指向新创建的对象xiaoming
- 为新对象创建
原型
,其实就是把新对象的__proto__
指向构造函数的prototype
手写new
上面我们了解了new
具体做了什么事情,那么它是怎么实现这些功能的呢?下面我们手写一个函数myNew
来模拟一下new
的效果:
//code-03