JavaScript面向对象精要(下部)


Posted in Javascript onSeptember 12, 2017

构造函数和原型对象

构造函数也是函数,用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

JavaScript面向对象精要(下部)

所以,实例中的指针仅指向原型,而不指向构造函数。 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");
}
Javascript 相关文章推荐
用js实现层随着内容大小动态渐变改变 推荐
Dec 19 Javascript
jQuery 仿百度输入标签插件附效果图
Jul 04 Javascript
JS+DIV+CSS排版布局实现美观的选项卡效果
Oct 10 Javascript
简介AngularJS中$http服务的用法
Feb 06 Javascript
JavaScript驾驭网页-CSS与DOM
Mar 24 Javascript
jQuery中Find选择器用法示例
Sep 21 Javascript
PHP7新特性简述
Jun 11 Javascript
原生javascript实现文件异步上传的实例讲解
Oct 26 Javascript
JavaScript模块详解
Dec 18 Javascript
给localStorage设置一个过期时间的方法分享
Nov 06 Javascript
微信小程序iBeacon测距及稳定程序的实现解析
Jul 31 Javascript
基于Vue全局组件与局部组件的区别说明
Aug 11 Javascript
在Vue.js中使用Mixins的方法
Sep 12 #Javascript
JavaScript面向对象精要(上部)
Sep 12 #Javascript
JS库之ParticlesJS使用简介
Sep 12 #Javascript
关于预加载InstantClick的问题解决方法
Sep 12 #Javascript
提升页面加载速度的插件InstantClick
Sep 12 #Javascript
详解如何让InstantClick兼容MathJax、百度统计等
Sep 12 #Javascript
使用InstantClick.js让页面提前加载200ms
Sep 12 #Javascript
You might like
PHP 文件上传源码分析(RFC1867)
2009/10/30 PHP
php 数组使用详解 推荐
2011/06/02 PHP
yii实现创建验证码实例解析
2014/07/31 PHP
php中上传文件的的解决方案
2018/09/25 PHP
prototype 1.5相关知识及他人笔记
2006/12/16 Javascript
用javascript实现的图片马赛克后显示并切换加文字功能
2007/04/21 Javascript
各浏览器对link标签onload/onreadystatechange事件支持的差异分析
2011/04/27 Javascript
JavaScript中的apply()方法和call()方法使用介绍
2012/07/25 Javascript
javascript时区函数介绍
2012/09/14 Javascript
JavaScript中的Math.LN2属性用法详解
2015/06/12 Javascript
JavaScript动态创建div等元素实例讲解
2016/01/06 Javascript
javascript验证香港身份证的格式或真实性
2017/02/07 Javascript
vue-cli中的babel配置文件.babelrc实例详解
2018/02/22 Javascript
解决VUE框架 导致绑定事件的阻止冒泡失效问题
2018/02/24 Javascript
vue中使用vee-validator完成表单校验方案
2019/11/01 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
vue 通过 Prop 向子组件传递数据的实现方法
2020/10/30 Javascript
python 自动提交和抓取网页
2009/07/13 Python
Python生成随机密码
2015/03/10 Python
python 网络编程常用代码段
2016/08/28 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
Python实现多线程下载脚本的示例代码
2020/04/03 Python
基于django和dropzone.js实现上传文件
2020/11/24 Python
快速一键生成Python爬虫请求头
2021/03/04 Python
CSS3 animation ? steps 函数详解
2019/08/30 HTML / CSS
FitFlop澳大利亚官网:英国符合人体工学的鞋类品牌
2017/06/05 全球购物
新闻专业推荐信范文
2013/11/20 职场文书
大学新生军训感言
2014/02/25 职场文书
大学班级计划书
2014/04/29 职场文书
优秀党员学习焦裕禄精神思想汇报范文
2014/09/10 职场文书
第一书记观后感
2015/06/08 职场文书
商场广播稿范文
2015/08/19 职场文书
2016年第32个教师节红领巾广播稿
2015/12/18 职场文书
“学党章、守党纪、讲党规”学习心得体会
2016/01/14 职场文书
国际最新研究在陨石中发现DNA主要成分 或由陨石带来地球
2022/04/29 数码科技
delete in子查询不走索引问题分析
2022/07/07 MySQL