原型是js里非常重要的一个概念,很多更高级的概念需要有原型的基础,类似于,我们js里的继承,原型就是其中一种实现方式,还有通过原型模式创建对象等等,这都需要原型基础,这里主要通过Chorme的调试器,来看看到底原型和对象到底是什么。
首先我们先写一些测试用的代码
function Person(){
var name = 'qfy';
var password = '123'
}
function Man(){
var name = 'ds';
var password = '12fsdf3'
}
Person.prototype.age = 23;
Person.prototype.name = 'li';
Person.prototype.say = function(name){
console.log(this.name)
}
Man.prototype.name = 'af';
Man.prototype.say = function(name){
console.log(this.name)
}
这是两个构造函数,分别是Person和Man,并且分别给两个构造函数的原型上添加了属性name
之后我们通过构造函数创建对象
var person = new Person()
我们看一下person在谷歌调试下console.log出了什么
是一个Person创建的对象,里面有一个__proto__
属性。这里面有有我们定义在Person原型上的name属性值,和say方法,还有一个constructor指向Person构造函数。
这里的__proto__
就是指向Person构造函数的原型,这就是原型链,属性都在原型链上,当我们的对象本身不存在这个属性是,就会向上查找原型链里是否包含属性。
console.log(person.__proto__ === Person.prototype)//true
person.say()// li 通过原型链找到了name=li,可以看到上面的__proto__历史有name属性的
person.__proto__ = new Man() //我们可以通过__proto__来调整原型链,虽然__proto__是浏览器的自己的属性,并不是标准的属性。
console.log(person.name) //af
当我们使用字面量方法定义prototype时,我们需要重新指定原型的构造函数指向
Person.prototype = {'name': 'li','head': 'sf'}
//指向了全局
console.log(Person.prototype.constructor)//function Object() { [native code] }
//我们需要在中间加一段代码,将指向还原
Person.prototype.constructor = Person;
我们可以通过最简单原型继承来更深的理解一下
var person = function(){
this.name = 'sfs'
};
person.prototype = new Person()
var person1 = new person()
person1.say()//sfs
console.log(person1)
继承了Person的say方法,和一些属性虽然new的是person,但依旧可以使用Person的方法
这就是原型链,我们可以通过他来一层一层的找。我们new的时候得到的都是原型链里的属性和方法,除非构造函数中用this,否则我们是访问不到的。