构造函数和原型对象

构造函数也是函数,用new创建对象时调用的函数,与普通函数的一个区别是,其首字母应该大写。但如果将构造函数当作普通函数调用(缺少new关键字),则应该注意this指向的问题。
var name = "Pomy";
function Per(){
console.log("Hello "+this.name);
}
var per1 = new Per(); //"Hello undefined"
var per2 = Per(); //"Hello Pomy"
使用new时,会自动创建this对象,其类型为构造函数类型,指向对象实例;缺少new关键字,this指向全局对象。
可以用instanceof来检测对象类型,同时每个对象在创建时都自动拥有一个constructor属性,指向其构造函数(字面量形式或Object构造函数创建的对象,指向Object,自定义构造函数创建的对象则指向它的构造函数)。
console.log(per1 instanceof Per); //true console.log(per1.constructor === Per); //true
每个对象实例都有一个内部属性:[[Prototype]],其指向该对象的原型对象。构造函数本身也具有prototype 属性指向原型对象。所有创建的对象都共享该原型对象的属性和方法。
function Person(){}
Person.prototype.name="dwqs";
Person.prototype.age=20;
Person.prototype.sayName=function()
{
alert(this.name);
};
var per1 = new Person();
per1.sayName(); //dwqs
var per2 = new Person();
per2.sayName(); //dwqs
alert(per1.sayName == per2.sayName); //true
所以,实例中的指针仅指向原型,而不指向构造函数。 ES5提供了hasOwnProperty()和isPropertyOf()方法来反应原型对象和实例之间的关系
alert(Person.prototype.isPrototypeOf(per2)); //true
per1.blog = "www.ido321.com";
alert(per1.hasOwnProperty("blog")); //true
alert(Person.prototype.hasOwnProperty("blog")); //false
alert(per1.hasOwnProperty("name")); //false
alert(Person.prototype.hasOwnProperty("name")); //true
因为原型对象的constructor属性是指向构造函数本身,所以在重写原型时,需要注意constructor属性的指向问题。
function Hello(name){
this.name = name;
}
//重写原型
Hello.prototype = {
sayHi:function(){
console.log(this.name);
}
};
var hi = new Hello("Pomy");
console.log(hi instanceof Hello); //true
console.log(hi.constructor === Hello); //false
console.log(hi.constructor === Object); //true
使用对象字面量形式改写原型对象改变了构造函数的属性,因此constructor指向Object,而不是Hello。如果constructor指向很重要,则需要在改写原型对象时手动重置其constructor属性
Hello.prototype = {
constructor:Hello,
sayHi:function(){
console.log(this.name);
}
};
console.log(hi.constructor === Hello); //true
console.log(hi.constructor === Object); //false
利用原型对象的特性,我们可以很方便的在JavaScript的内建原型对象上添加自定义方法:
Array.prototype.sum=function(){
return this.reduce(function(prev,cur){
return prev+cur;
});
};
var num = [1,2,3,4,5,6];
var res = num.sum();
console.log(res); //21
String.prototype.capit = function(){
return this.charAt(0).toUpperCase()+this.substring(1);
};
var msg = "hello world";
console.log(msg.capit()); //"Hello World"
继承
利用[[Prototype]]特性,可以实现原型继承;对于字面量形式的对象,会隐式指定Object.prototype为其[[Prototype]],也可以通过Object.create()显示指定,其接受两个参数:第一个是[[Prototype]]指向的对象(原型对象),第二个是可选的属性描述符对象。
var book = {
title:"这是书名";
};
//和下面的方式一样
var book = Object.create(Object.prototype,{
title:{
configurable:true,
enumerable:true,
value:"这是书名",
wratable:true
}
});
字面量对象会默认继承自Object,更有趣的用法是,在自定义对象之间实现继承。
var book1 = {
title:"JS高级程序设计",
getTitle:function(){
console.log(this.title);
}
};
var book2 = Object.create(book1,{
title:{
configurable:true,
enumerable:true,
value:"JS权威指南",
wratable:true
}
});
book1.getTitle(); //"JS高级程序设计"
book2.getTitle(); //"JS权威指南"
console.log(book1.hasOwnProperty("getTitle")); //true
console.log(book1.isPrototypeOf("book2")); //false
console.log(book2.hasOwnProperty("getTitle")); //false
当访问book2的getTitle属性时,JavaScript引擎会执行一个搜索过程:现在book2的自有属性中寻找,找到则使用,若没有找到,则搜索[[Prototype]],若没有找到,则继续搜索原型对象的[[Prototype]],直到继承链末端。末端通常是Object.prototype,其[[Prototype]]被设置为null。
实现继承的另外一种方式是利用构造函数。每个函数都具有可写的prototype属性,默认被自懂设置为继承自Object.prototype,可以通过改写它来改变原型链。
function Rect(length,width){
this.length = length;
this.width = width;
}
Rect.prototype.getArea = function(){
return this.width * this.length;
};
Rect.prototype.toString = function(){
return "[Rect"+this.length+"*"+this.width+"]";
};
function Square(size){
this.length = size;
this.width = size;
}
//修改prototype属性
Square.prototype = new Rect();
Square.prototype.constructor = Square;
Square.prototype.toString = function(){
return "[Square"+this.length+"*"+this.width+"]";
};
var rect = new Rect(5,10);
var square = new Square(6);
console.log(rect.getArea()); //50
console.log(square.getArea()); //36
如果要访问父类的toString(),可以这样做:
Square.prototype.toString = function(){
var text = Rect.prototype.toString.call(this);
return text.replace("Rect","Square");
}
# js面向对象
# JavaScript面向对象精要(上部)
# 自定义
# 这是
# 可以通过
# 重写
# 设置为
# 没有找到
# 程序设计
# 都有
# 第一个
# 可以用
# 要在
# 我们可以
# 而不
# 第二个
# 这样做
# 很重要
# 为其
# 可选
# 可以实现
# 内建
相关文章:
如何高效完成独享虚拟主机建站?
制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?
如何在阿里云购买域名并搭建网站?
网站微信制作软件,如何制作微信链接?
洛阳网站制作公司有哪些,洛阳的招聘网站都有哪些?
电脑免费海报制作网站推荐,招聘海报哪个网站多?
孙琪峥织梦建站教程如何优化数据库安全?
如何在腾讯云服务器上快速搭建个人网站?
小型网站建站如何选择虚拟主机?
沈阳个人网站制作公司,哪个网站能考到沈阳事业编招聘的信息?
建站之星五站合一营销型网站搭建攻略,流量入口全覆盖优化指南
高防服务器如何保障网站安全无虞?
如何通过多用户协作模板快速搭建高效企业网站?
简易网站制作视频教程,使用记事本编写一个简单的网页html文件?
h5网站制作工具有哪些,h5页面制作工具有哪些?
建站主机选购指南与交易推荐:核心配置解析
建站ABC备案流程中有哪些关键注意事项?
如何快速生成凡客建站的专业级图册?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
哈尔滨网站建设策划,哈尔滨电工证查询网站?
网站制作新手教程,新手建设一个网站需要注意些什么?
制作充值网站的软件,做人力招聘为什么要自己交端口钱?
建站之星后台管理系统如何操作?
建站主机类型有哪些?如何正确选型
如何安全更换建站之星模板并保留数据?
广州美橙建站如何快速搭建多端合一网站?
建站主机助手选型指南:2025年热门推荐与高效部署技巧
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
中山网站推广排名,中山信息港登录入口?
Java解压缩zip - 解压缩多个文件或文件夹实例
制作营销网站公司,淘特是干什么用的?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
油猴 教程,油猴搜脚本为什么会网页无法显示?
定制建站方案优化指南:企业官网开发与建站费用解析
制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
深圳网站制作的公司有哪些,dido官方网站?
如何通过远程VPS快速搭建个人网站?
外贸公司网站制作,外贸网站建设一般有哪些步骤?
如何高效生成建站之星成品网站源码?
建站之星价格显示格式升级,你的预算足够吗?
,南京靠谱的征婚网站?
制作门户网站的参考文献在哪,小说网站怎么建立?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
如何快速生成可下载的建站源码工具?
*请认真填写需求信息,我们会在24小时内与您取得联系。