举例说明JavaScript中的实例对象与原型对象


Posted in Javascript onMarch 11, 2016

首先声明:javascript中每个对象都有一个constructor属性和一个prototype属性。constructor指向对象的构造函数,prototype指向使用构造函数创建的对象实例的原型对象。

function Person(){ 
  
 } 
var person = new Person(); 
 
Person.prototype = { 
 constructor : Person, 
 name : 'zxs', 
 age : 24, 
 sayName : function(){alert(this.name)} 
 } 
  
person.sayName();

在这段代码中会报错,sayName() is not defined。根据javascript高级程序设计第二版的解释,是因为重写的原型切断了构造函数与最初原型之间的联系。但是我们调整一下上面语句的顺序。如下:

function Person(){ 
 } 
//var person = new Person(); 
Person.prototype = { 
 constructor : Person, 
 name : 'zxs', 
 age : 24, 
 sayName : function(){alert(this.name)} 
} 
/*===========================================================*/ 
var person = new Person(); 
/*===========================================================*/ 
 person.sayName(); // zxs 
alert(person.constructor) //function Object() { [native code]} or function Person() {} 取决与蓝色的语句是否有效

注意上面两段代码等号中间的语句。按第二段的顺序写代码,将会输出 ”zxs“,这个结果说明在第一种情况下报错并不能说明是因为切断了构造函数与原想之间的联系引起的。

Person.prototype = {}

本来就是一种定义对象的方法,而且在javascript中每个对象的constructor属性都默认的指向Object构造函数,这也就不难说明重写原型对象确实切断了构造函数与最初原型之间的联系,但并不能说明这种联系被切断之后 person就不能访问到sayName()函数。

现在有这样的假设:函数的prototype属性所指向的原型对象,与我们显示新建的原型对象并不是完全等同的。当我们调用函数的时候会创建一个原型对象,此时会首先查找当前环境中是否存在其原型对象,如果程序中不存在,就创建一个,如果环境中存在,侧查找他们的属性和方法,最后根据查找的结果返回一个原型对象,这个对象中的属性和方法总是优先使用默认原型中的属性和方法,也就是构造函数中定义的属性和方法。当当调用的方法或属性不存在于默认的原型中时,才使用定义在Person.prototype = {} 的属性和方法。

javascript是解释性的语言,语句都是顺序执行的,在第一段代码中,当我们使用 new 关键字创建新对象的时候,Person.prototype = {} 并没有执行,也就是说在当前的执行环境中找不到其中定义的方法和属性,而构造函数中没有该方法,所以出错。就像一个变量,给他赋值的时候程序没有执行将不能使用。在第二段中环境中已经存在该调用的方法,构造函数的原型对象已经创建完毕,所以可以得到结果。

再看下面的一段程序:

////////////////////////////////////////////////////////////////////////// 
 
function Person(){} 
 
/*===========================================================*/ 
 
 var person = new Person(); 
Person.prototype.name = 'song'; 
 
/*===========================================================*/ 
 
//Person.prototype.sayName = function(){alert(this.name)}; 
Person.prototype = { 
constructor : Person, 
name : 'zxs', 
age : 24, 
sayName : function(){alert(this.name)} 
} 
person.sayName(); // error 
 
////////////////////////////////////////////////////////////////////////// 
 
function Person(){  } 
/*var person = new Person();*/ 
Person.prototype.name = 'song';  
/*Person.prototype.sayName = function(){alert(this.name)};*/ 
Person.prototype = {   
constructor : Person, 
  name : 'zxs', 
  age : 24, 
  sayName : function(){alert(this.name)} 
} 
 
/*===========================================================*/ 
var person = new Person(); 
 
/*===========================================================*/ 
person.sayName(); // zxs

从这里可以看出使用 Person.prototype.name = '',的方式不论在什么地方创建对象都能被访问,如果同时存在对象字面量和这种方法定义原型对象,将使用后定义的作为最终值。并且对原型对象使用对象字面量定义之后,该定义必须出现在创建对象的语句之前才能被访问到。

实例不能访问到原型对象中的属性和方法,不仅仅是因为重写原型对象切断了构造函数与最初原型之间的联系。

function Person(){  
    
  }  
var person = new Person();  
  
Person.prototype = {  
  //constructor : Person,  
  name : 'zxs',  
  age : 24,  
  sayName : function(){alert(this.name)}  
  }  
    
person.sayName();

以上代码在实例化对象时构造函数的原型为空,它没有任何除默认属性以外的属性。重写构造函数的原型确实切断了构造函数与最初原型之间的联系。

在使用 new 操作符以后构造函数的原型对象中的属性和方法已经添加到 person对象中。因为以上方法为函数原型添加新属性和方法不具有动态性,所以person不能访问到新添加的属性和方法。

重写原型对象之后,就如同如下代码:

var o = { 
  name : 'zxs' 
  } 
   
var obj = o; 
o = {} 
console.log(o.name);

此时输出的值是undefined,因为,对象是一个引用类型,“=”是赋值操作符,并且其运算顺序是从右往左。o={}就是说o的指向已经改变,是一个空对象。
Person.prototype.mothed = function() {}与Person.prototype={mothed:function(){}}的区别就如同 arr = []和arr.push()一样,前者都是修改自身,后者是完全改变自身。

Javascript 相关文章推荐
Extjs4 GridPanel 的几种样式使用介绍
Apr 18 Javascript
js操作iframe兼容各种主流浏览器示例代码
Jul 22 Javascript
基于jQuery实现表单提交验证
Nov 24 Javascript
JQuery中Bind()事件用法分析
May 05 Javascript
jQuery结合ajax实现动态加载文本内容
May 19 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
Dec 01 Javascript
jquery插件jquery.dragscale.js实现拖拽改变元素大小的方法(附demo源码下载)
Feb 25 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
Aug 25 Javascript
深入理解Vue-cli搭建项目后的目录结构探秘
Jul 13 Javascript
微信小程序movable view移动图片和双指缩放实例代码
Aug 08 Javascript
vue中,在本地缓存中读写数据的方法
Sep 21 Javascript
原生js实现滑块区间组件
Jan 20 Javascript
JavaScript中setTimeout和setInterval函数的传参及调用
Mar 11 #Javascript
原生JavaScript制作微博发布面板效果
Mar 11 #Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
Mar 11 #Javascript
详解Angularjs中的依赖注入
Mar 11 #Javascript
详解AngularJS过滤器的使用
Mar 11 #Javascript
javascript html5 canvas实现可拖动省份的中国地图
Mar 11 #Javascript
js仿百度登录页实现拖动窗口效果
Mar 11 #Javascript
You might like
PHP通过iconv将字符串从GBK转换为UTF8字符集
2011/07/18 PHP
PHP常用特殊运算符号和函数总结(php新手入门必看)
2013/02/02 PHP
yii框架使用分页的方法分析
2019/07/25 PHP
flash 得到自身url参数的代码
2009/11/15 Javascript
javascript 四则运算精度修正函数代码
2010/05/31 Javascript
js setTimeout opener的用法示例详解
2013/10/23 Javascript
js获得参数的getParameter使用示例
2014/02/26 Javascript
开发中可能会用到的jQuery小技巧
2014/03/07 Javascript
jquery中$(#form :input)与$(#form input)的区别
2014/08/18 Javascript
javascript瀑布流式图片懒加载实例
2020/06/28 Javascript
js的form表单提交url传参数(包含+等特殊字符)的两种解决方法
2016/05/25 Javascript
全面解析JS字符串和正则表达式中的match、replace、exec等函数
2016/07/01 Javascript
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
Node.js中你不可不精的Stream(流)
2018/06/08 Javascript
Vue.js 图标选择组件实践详解
2018/12/03 Javascript
JavaScript使用闭包模仿块级作用域操作示例
2019/01/21 Javascript
《javascript设计模式》学习笔记四:Javascript面向对象程序设计链式调用实例分析
2020/04/07 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
2015/03/19 Python
解析Python中的生成器及其与迭代器的差异
2016/06/20 Python
利用python程序帮大家清理windows垃圾
2017/01/15 Python
Python如何读取文件中图片格式
2020/01/13 Python
深入浅析css3 border-image边框图像详解
2015/11/24 HTML / CSS
英国家喻户晓的家居商店:The Range
2019/03/25 全球购物
Dr. Martens马汀博士法国官网:马丁靴鼻祖
2020/01/15 全球购物
接待员岗位责任制
2014/02/10 职场文书
优秀家长事迹材料
2014/05/17 职场文书
一般党员对照检查材料
2014/09/24 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
实名检举信范文
2015/03/02 职场文书
2015年政协委员工作总结
2015/05/20 职场文书
管辖权异议上诉状
2015/05/23 职场文书
网聊搭讪开场白
2015/05/28 职场文书
2020年基层司法所建设情况调研报告
2019/11/30 职场文书
解决pycharm下载库时出现Failed to install package的问题
2021/09/04 Python
python基础之类方法和静态方法
2021/10/24 Python