举例说明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 相关文章推荐
[原创]js获取数组任意个不重复的随机数组元素
Mar 15 Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 Javascript
从盛大通行证上摘下来的身份证验证js代码
Jan 11 Javascript
JavaScript instanceof 的使用方法示例介绍
Oct 23 Javascript
js call方法详细介绍(js 的继承)
Nov 18 Javascript
弹出遮罩层后禁止滚动效果【实现代码】
Apr 29 Javascript
JS奇技之利用scroll来监听resize详解
Jun 15 Javascript
AngularJs+Bootstrap实现漂亮的计算器
Aug 10 Javascript
vue debug 二种方法
Sep 16 Javascript
JS中如何轻松遍历对象属性的方式总结
Aug 06 Javascript
在vue中实现echarts随窗体变化
Jul 27 Javascript
Vue图片裁剪组件实例代码
Jul 02 Vue.js
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 addslashes和mysql_real_escape_string
2010/01/24 PHP
PHP结合jQuery实现找回密码
2015/07/22 PHP
ThinkPHP模板循环输出Volist标签用法实例详解
2016/03/23 PHP
php mysql实现mysql_select_db选择数据库
2016/12/30 PHP
使用PHPStorm+XDebug搭建单步调试环境
2017/11/19 PHP
firefox浏览器下javascript 拖动层效果与原理分析代码
2007/12/04 Javascript
ie focus bug 解决方法
2009/09/03 Javascript
javascript中的一些注意事项 更新中
2010/12/06 Javascript
jquery命令汇总,方便使用jquery的朋友
2012/06/26 Javascript
指定区域的图片自动按比例缩小的js代码(防止页面被图片撑破)
2014/02/21 Javascript
jquery实现LED广告牌旋转系统图片切换效果代码分享
2015/08/26 Javascript
JavaScript判断按钮被点击的方法
2015/12/13 Javascript
深入理解JavaScript中的对象复制(Object Clone)
2016/05/18 Javascript
Js删除数组中某一项或几项的几种方法(推荐)
2016/07/27 Javascript
JS对象是否拥有某属性如何判断
2017/02/03 Javascript
angular2 ng build部署后base文件路径问题详细解答
2017/07/15 Javascript
关于meta viewport中target-densitydpi属性详解(推荐)
2017/08/18 Javascript
BootStrap中Table隐藏后显示问题的实现代码
2017/08/31 Javascript
jQuery实现雪花飘落效果
2020/08/02 jQuery
通过JS判断网页是否为手机打开
2020/10/28 Javascript
[01:01:52]完美世界DOTA2联赛PWL S2 GXR vs Magma 第二场 11.25
2020/11/26 DOTA
分析python服务器拒绝服务攻击代码
2014/01/16 Python
python在文本开头插入一行的实例
2018/05/02 Python
关于torch.optim的灵活使用详解(包括重写SGD,加上L1正则)
2020/02/20 Python
python实现FTP文件传输的方法(服务器端和客户端)
2020/03/20 Python
Python新手学习装饰器
2020/06/04 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
周年庆典邀请函范文
2014/01/24 职场文书
综治工作心得体会
2014/09/11 职场文书
买卖合同协议书范本
2014/10/18 职场文书
《钓鱼的启示》教学反思
2016/02/18 职场文书
接触艺术对孩子学习思维有益
2019/08/06 职场文书
创业计划书之牛肉汤快餐店
2019/10/08 职场文书
anaconda python3.8安装后降级
2021/06/11 Python
七个非常实用的Python工具包总结
2021/06/15 Python
纯 CSS 自定义多行省略的问题(从原理到实现)
2021/11/11 HTML / CSS