举例说明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 相关文章推荐
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 Javascript
javascript创建createXmlHttpRequest对象示例代码
Feb 10 Javascript
js中的onchange和onpropertychange (onchange无效的解决方法)
Mar 08 Javascript
使用node.js 获取客户端信息代码分享
Nov 26 Javascript
Vue实现typeahead组件功能(非常靠谱)
Aug 26 Javascript
详谈Node.js之操作文件系统
Aug 29 Javascript
jquery学习笔记之无new构建详解
Dec 07 jQuery
Vue服务端渲染实践之Web应用首屏耗时最优化方案
Mar 22 Javascript
微信小程序云开发如何实现数据库自动备份实现
Aug 16 Javascript
D3.js 实现带伸缩时间轴拓扑图的示例代码
Jan 20 Javascript
jQuery实现广告显示和隐藏动画
Jul 04 jQuery
Javascript使用integrity属性进行安全验证
Nov 07 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
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
2007/05/03 PHP
首页四格,首页五格For6.0(GBK)(UTF-8)[12种组合][9-18][版主安装测试通过]
2007/09/24 PHP
微博短链接算法php版本实现代码
2012/09/15 PHP
如何设置mysql允许外网访问
2013/06/04 PHP
php实现根据词频生成tag云的方法
2015/04/17 PHP
php实现跨域提交form表单的方法【2种方法】
2016/10/17 PHP
PHP+MYSQL实现读写分离简单实战
2017/03/13 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
2017/06/06 PHP
php实现微信模拟登陆、获取用户列表及群发消息功能示例
2017/06/28 PHP
jquery 必填项判断表单是否为空的方法
2008/09/14 Javascript
JavaScript CSS修改学习第三章 修改样式表
2010/02/19 Javascript
jquery实现文字由下到上循环滚动的实例代码
2013/08/09 Javascript
2014 年最热门的21款JavaScript框架推荐
2014/12/25 Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
2016/07/05 Javascript
jQuery中的deferred使用方法
2017/03/27 jQuery
深入理解React Native原生模块与JS模块通信的几种方式
2017/07/24 Javascript
Angular4 中内置指令的基本用法
2017/07/31 Javascript
React应用中使用Bootstrap的方法
2017/08/15 Javascript
微信小程序实现YDUI的ScrollTab组件
2018/02/02 Javascript
关于Vue在ie10下空白页的debug小结
2018/05/02 Javascript
详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
2018/07/24 Javascript
微信jssdk逻辑在vue中的运用详解
2018/11/14 Javascript
一个基于flask的web应用诞生 组织结构调整(7)
2017/04/11 Python
Python math库 ln(x)运算的实现及原理
2019/07/17 Python
基于python调用psutil模块过程解析
2019/12/20 Python
印度网上购物首选目的地:Flipkart
2016/08/01 全球购物
美国迪克体育用品商店:DICK’S Sporting Goods
2018/07/24 全球购物
戴尔新加坡官网:Dell Singapore
2020/12/13 全球购物
美工的岗位职责
2013/11/14 职场文书
九年级物理教学反思
2014/01/29 职场文书
家长会主持词
2014/03/26 职场文书
汉语言文学毕业求职信
2014/07/17 职场文书
食品安全承诺书范文
2014/08/29 职场文书
师德师风事迹材料
2014/12/20 职场文书
2016春季校长开学典礼致辞
2015/11/26 职场文书
人为什么会“幸灾乐祸”?
2019/08/06 职场文书