学习JavaScript时,就一定会涉及到两个概念–prototype,原型对象。自己在做项目时可能无意中使用到,但是却没有真正去了解这个东西,在学会使用的基础上,进一步去理解它会帮助自己吸收到更多不一样的知识。
1.Prototype
prototype
翻译过来称为"原型"。prototype
是每个函数都具有的一个属性,这个属性是一个指针,指向这个函数的原型对象,而且每个该对象产生的实例对象(new 操作符创建)都可以共享该对象prototype
属性上的所有属性和方法。
2.原型对象
那么指向的原型对象又是怎么样的呢?通过创建一个简单的构造函数,打印该实例对象可以更好的去理解。
function Person() {
}
var p = new Person(); //创建的一个Person类型的实例
console.log(p instanceof Person) //true
console.log(p)
谷歌浏览器打印p
的结果:
这里的Person
是一个空的构造函数,什么都没有。只有一个__proto__
属性,他的类型可以看到是一个Object
对象。这个对象我们其实并没有定义,这个对象就是Person的原型对象。
通过下面的打印进一步验证:
console.log(p.__proto__ === Person.prototype) //true
这个__proto__
是浏览器支持的一个属性,这个属性这个实例内部的一个指针,指向这个实例的构造函数的原型对象,也就是Person.prototype
.原型对象的结构是这样的
Perosn
的原型对象会自动获得一个constructor
属性,这个属性指向其prototype
属性所在函数,也就是指向Person
,通过打印比较可以验证
console.log(p.__proto__.constructor === Person) //true
同时还从Object
那里继承过来了一些方法,如常用的hasOwnProperty
,toString
等。这些原型方法可以直接被实例调用,也可以被重写。
3.原型对象的拓展
我们可以在原型对象上定义自己的方法和属性,可以将对象之间都需要用到的一些共用方法和属性定义在这上面,这样每个对象的实例不需要自己在函数里各自又重复写一遍代码来实现相同功能的方法。
//页面
function Page(id, title){
this.id = id;
this.title = title;
this.$div = $("#"+id);
this.init()
}
//显示
Page.prototype.show = function(){
this.$div.show();
}
//隐藏
Page.prototype.hide = function(){
this.$div.hide();
}
//这里的prototype上的title并没有生效。因为解析器在查询属性值过程中先从自身实例坐在函数内部先进行查询,如果没有找到的情况下则顺着原型链一步步查询下去
Page.prototype.title = "我是标题";
//初始化
Page.prototype.init = function() {
this.$div.find(".title").html(this.title)
}
//获取内容
Page.prototype.getContent = function() {
var content = this.$div.find(".content").html();
return content;
}
var userPage = new Page("page-user","用户详情");
var logPage = new Page("page-log","日志详情");
var userContent = userPage.getContent();
var logContent = logPage.getContent();
console.log(userContent) //我是用户界面
console.log(logContent) //我是日志界面
上面的构造函数通过传入不同的id管理对应不同的页面对象。每个页面实例之间都可以使用show()
,hide()
方法,每个实例都各自管理着自己的属性,这样每个实例之间的修改不会影响其他实例。
4.总结
直接用一张图表示