理解Javascript_06_理解对象的创建过程


Posted in Javascript onOctober 15, 2010

简单的代码
我们先来看一段简单的代码:

function HumanCloning(){ 
} 
HumanCloning.prototype ={ 
name:'笨蛋的座右铭' 
} 
var clone01 = new HumanCloning(); 
alert(clone01.name);//'笨蛋的座右铭' 
alert(clone01 instanceof HumanCloning);//true 
HumanCloning.prototype = {}; 
alert(clone01.name);//'笨蛋的座右铭' 
alert(clone01 instanceof HumanCloning);//false 
var clone02 = new HumanCloning(); 
alert(clone02.name);//undefined 
alert(clone02 instanceof HumanCloning);//true

复杂的理论
JS中只有函数对象(函数)具备类的概念,因此创建一个对象,必须使用函数对象。函数对象内部有[[Construct]]方法和[[Call]]方法,[[Construct]]用于构造对象,[[Call]]用于函数调用,只有使用new操作符时才触发[[Construct]]逻辑。注:在本例中HumanCloning这个自定义函数是一个函数对象,那么请问Object,String,Number等本地对象是函数对象吗?答案是肯定的,这是因为本地对象都可以看作是函数的派生类型,在这个意义上,可以将它们跟用户定义的函数等同看待。(与《理解Javascript_04_数据模型》中"内置数据类型"一节相呼应)
var obj=new Object(); 是使用内置的Object这个函数对象创建实例化对象obj。var obj={};和var obj=[];这种代码将由JS引擎触发Object和Array的构造过程。function fn(){}; var myObj=new fn();是使用用户定义的类型创建实例化对象。
注:关于函数对象的具体概念会在后续的文章中讲解,现在可以将"函数对象"简单的理解为"函数"的概念及可.

内部的实现
结合本例,函数对象为HumanCloning,函数对象创建的对象实例为clone01和clone02. 现在我们来看一下var clone01 = new HumanCloning();的实现细节(注:函数对象的[[Construct]]方法处理逻辑来负责实现对象的创建):
1. 创建一个build-in object对象obj并初始化
2. 如果HumanCloning.prototype是Object类型,则将clone01的内部[[Prototype]]设置为HumanCloning.prototype,否则clone01的[[Prototype]]将为其初始化值(即Object.prototype)
3. 将clone01作为this,使用args参数调用HumanCloning的内部[[Call]]方法
3.1 内部[[Call]]方法创建当前执行上下文(注:关于执行上下文,将在后续博文中讲解,在《Javascript提速_01_引用变量优化》一文中已有部分讲解》)
3.2 调用HumanCloning的函数体
3.3 销毁当前的执行上下文
3.4 返回HumanCloning函数体的返回值,如果HumanCloning的函数体没有返回值则返回undefined
4. 如果[[Call]]的返回值是Object类型,则返回这个值,否则返回obj
注意,如下代码为步骤1,步骤2和步骤3的代码解释:

var clone01 = {}; 
//程序外部是无法访问[[prototype]]的,仅用于理解 
//clone01.[[prototype]] = HumanCloning.prototype; 
HumanCloning.call(clone01);

注意步骤2中, prototype指对象显示的prototype属性,而[[Prototype]]则代表对象内部Prototype属性(隐式的)。构成对象Prototype链的是内部隐式的[[Prototype]],而并非对象显示的prototype属性。显示的prototype只有在函数对象上才有意义,从上面的创建过程可以看到,函数的prototype被赋给派生对象隐式[[Prototype]]属性,这样根据Prototype规则,派生对象和函数的prototype对象之间才存在属性、方法的继承/共享关系。(即原型继承实现原理,正是《理解Javascript_05_原型继承原理》的内容)
注意步骤3.4中描述,让我们来看一个来自于怿飞的问题:
理解Javascript_06_理解对象的创建过程

我想,现在回答这个问题,应该是易如反掌吧。

注:原文地址http://www.planabc.net/2008/02/20/javascript_new_function/

内存分析
理解Javascript_06_理解对象的创建过程
一张简易的内存图,并引入的函数对象的概念,同样也解释了上面代码(相对来说图不是很严谨,但易于理解)。在此也引出了一个问题,instanceof的实现原理,想必大家也看出了一些苗头,instanceof的判断依赖于原型链,具体实现细节,请参见后续博文。
本地属性与继承属性
对象通过隐式Prototype链能够实现属性和方法的继承,但prototype也是一个普通对象,就是说它是一个普通的实例化的对象,而不是纯粹抽象的数据结构描述。所以就有了这个本地属性与继承属性的问题。
首先看一下设置对象属性时的处理过程。JS定义了一组attribute,用来描述对象的属性property,以表明属性property是否可以在JavaScript代码中设值、被for in枚举等。
obj.propName=value的赋值语句处理步骤如下:
1. 如果propName的attribute设置为不能设值,则返回
2. 如果obj.propName不存在,则为obj创建一个属性,名称为propName
3. 将obj.propName的值设为value
可以看到,设值过程并不会考虑Prototype链,道理很明显,obj的内部[[Prototype]]是一个实例化的对象,它不仅仅向obj共享属性,还可能向其它对象共享属性,修改它可能影响其它对象。
我们来看一个示例:

function HumanCloning(){ 
} 
HumanCloning.prototype ={ 
name:'笨蛋的座右铭' 
} 
var clone01 = new HumanCloning(); 
clone01.name = 'jxl'; 
alert(clone01.name);//jxl 
var clone02 = new HumanCloning(); 
alert(clone02.name);//笨蛋的座右铭

结果很明确,对象的属性无法修改其原型中的同名属性,而只会自身创建一个同名属性并为其赋值。
参考。
https://3water.com/article/25008.htm
Javascript 相关文章推荐
js arguments对象应用介绍
Nov 28 Javascript
js中浮点型运算BUG的解决方法说明
Jan 06 Javascript
快速掌握Node.js环境的安装与运行方法
Feb 16 Javascript
Vue.js每天必学之数据双向绑定
Sep 05 Javascript
Javascript 事件冒泡机制详细介绍
Oct 10 Javascript
Angular2-primeNG文件上传模块FileUpload使用详解
Jan 14 Javascript
angular.JS实现网页禁用调试、复制和剪切
Mar 31 Javascript
用js屏蔽被http劫持的浮动广告实现方法
Aug 10 Javascript
Angular请求防抖处理第一次请求失效问题
May 17 Javascript
详解在Angular4中使用ng2-baidu-map的方法
Jun 19 Javascript
javascript 数组精简技巧小结
Feb 26 Javascript
vue element table中自定义一些input的验证操作
Jul 18 Javascript
JavaScript聚焦于第一个字段的代码
Oct 15 #Javascript
JavaScript访问样式表代码
Oct 15 #Javascript
IE下js调试工具Companion.JS
Oct 15 #Javascript
jquery $.ajax各个事件执行顺序
Oct 15 #Javascript
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
Oct 15 #Javascript
jquery 元素相对定位代码
Oct 15 #Javascript
JQuery小知识
Oct 15 #Javascript
You might like
wordpress安装过程中遇到中文乱码的处理方法
2015/04/21 PHP
mod_php、FastCGI、PHP-FPM等PHP运行方式对比
2015/07/02 PHP
详解PHP防止直接访问.php 文件的实现方法
2017/07/28 PHP
基于jQuery的固定表格头部的代码(IE6,7,8测试通过)
2010/05/18 Javascript
刷新页面的几种方法小结(JS,ASP.NET)
2014/01/07 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
jQuery学习笔记之基础中的基础
2015/01/19 Javascript
分享一个自己写的简单的javascript分页组件
2015/02/15 Javascript
JS 作用域与作用域链详解
2015/04/07 Javascript
JavaScript的RequireJS库入门指南
2015/07/01 Javascript
js判断主流浏览器类型和版本号的简单实现代码
2016/05/26 Javascript
JavaScript中闭包的写法和作用详解
2016/06/29 Javascript
原生JavaScript来实现对dom元素class的操作方法(推荐)
2017/08/16 Javascript
vue2.0+ 从插件开发到npm发布的示例代码
2018/04/28 Javascript
使用vue-cli导入Element UI组件的方法
2018/05/16 Javascript
Vue.js 中 axios 跨域访问错误问题及解决方法
2018/11/21 Javascript
详解Vue中watch对象内属性的方法
2019/02/01 Javascript
微信小程序云开发如何使用云函数生成二维码
2019/05/18 Javascript
python实现按任意键继续执行程序
2016/12/30 Python
Python基于list的append和pop方法实现堆栈与队列功能示例
2017/07/24 Python
Flask 让jsonify返回的json串支持中文显示的方法
2018/03/26 Python
python 获取指定文件夹下所有文件名称并写入列表的实例
2018/04/23 Python
Python文件监听工具pyinotify与watchdog实例
2018/10/15 Python
python数据处理之如何选取csv文件中某几行的数据
2019/09/02 Python
python属于解释型语言么
2020/06/15 Python
分享PyCharm最新激活码(真永久激活方法)不用每月找安装参数或最新激活码了
2020/12/27 Python
如何用Python进行时间序列分解和预测
2021/03/01 Python
CSS3 实现穿梭星空动画
2020/11/13 HTML / CSS
Jabra捷波朗美国官网:用于办公、车载和运动的无线蓝牙耳麦
2017/02/01 全球购物
ASOS亚洲:ASOS Asia
2018/03/04 全球购物
Made in Design英国:设计家具、照明、家庭装饰和花园家具
2019/09/24 全球购物
No7 Beauty美国官网:英国国民护肤品牌
2019/10/31 全球购物
中学生打架检讨书
2014/10/13 职场文书
分家协议书范本
2016/03/22 职场文书
党组织结对共建协议书
2016/03/23 职场文书
《飘》英文读后感五篇
2019/10/11 职场文书