全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

JavaScript面向对象精要(下部)

构造函数和原型对象

构造函数也是函数,用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小时内与您取得联系。