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 相关文章推荐
TopList标签和JavaScript结合两例
Aug 12 Javascript
jquery入门——事件机制之事件中的冒泡现象示例解释
Sep 12 Javascript
Js,alert出现乱码问题的解决方法
Jun 19 Javascript
js实现简单的联动菜单效果
Aug 19 Javascript
js放大镜放大购物图片效果
Jan 18 Javascript
vue.js中mint-ui框架的使用方法
May 12 Javascript
jquery实现限制textarea输入字数的方法
Sep 06 jQuery
如何编写一个完整的Angular4 FormText 组件
Nov 18 Javascript
简化vuex的状态管理方案的方法
Jun 02 Javascript
移动端手指操控左右滑动的菜单
Sep 08 Javascript
javascript实现电商放大镜效果
Nov 23 Javascript
js实现移动端轮播图滑动切换
Dec 21 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实现根据图片色界在不同位置加水印的方法
2015/08/08 PHP
PHP7标量类型declare用法实例分析
2016/09/26 PHP
tp5.1框架数据库子查询操作实例分析
2020/05/26 PHP
JSON为什么那样红为什么要用json(另有洞天)
2012/12/26 Javascript
CSS+jQuery实现的一个放大缩小动画效果
2013/09/24 Javascript
jquery实现input输入框实时输入触发事件代码
2014/01/28 Javascript
使用jquery实现以post打开新窗口
2014/03/19 Javascript
JavaScript中双叹号(!!)作用示例介绍
2014/04/10 Javascript
jQuery实现回车键(Enter)切换文本框焦点的代码实例
2014/05/05 Javascript
jQuery之Deferred对象详解
2014/09/04 Javascript
浅谈JSON.parse()和JSON.stringify()
2015/07/14 Javascript
js+css实现有立体感的按钮式文字竖排菜单效果
2015/09/01 Javascript
JS实现的自定义右键菜单实例二则
2015/09/01 Javascript
js省市联动效果完整实例代码
2015/12/09 Javascript
chrome浏览器如何断点调试异步加载的JS
2016/09/05 Javascript
浅谈JavaScript的自动垃圾收集机制
2016/12/15 Javascript
使用 jQuery 实现表单验证功能
2017/07/05 jQuery
JS与HTML结合实现流程进度展示条思路详解
2017/09/03 Javascript
CheckBox多选取值及判断CheckBox选中是否为空的实例
2017/10/31 Javascript
jQuery+Cookie实现切换皮肤功能【附源码下载】
2018/03/25 jQuery
layui自定义插件citySelect实现省市区三级联动选择
2019/07/26 Javascript
Python减少循环层次和缩进的技巧分析
2016/03/15 Python
Python正则表达式使用经典实例
2016/06/21 Python
Python单例模式实例详解
2017/03/01 Python
python 批量修改/替换数据的实例
2018/07/25 Python
PyQt5 对图片进行缩放的实例
2019/06/18 Python
Python3.6+selenium2.53.6自动化测试_读取excel文件的方法
2019/09/06 Python
Pytorch 实现focal_loss 多类别和二分类示例
2020/01/14 Python
Python实现清理微信僵尸粉功能示例【基于itchat模块】
2020/05/29 Python
html5 canvas实现跟随鼠标旋转的箭头
2016/03/11 HTML / CSS
美国知名男士服饰品牌:Brooks Brothers(布克兄弟)
2016/08/25 全球购物
欧缇丽美国官网:Caudalie美国
2016/12/31 全球购物
在线购买世界上最好的酒:BoozeBud
2018/06/07 全球购物
幼儿园门卫岗位职责
2014/02/14 职场文书
幼儿教师辞职信
2015/02/27 职场文书
分享node.js实现简单登录注册的具体代码
2022/04/26 NodeJs