Javascript new关键字的玄机 以及其它


Posted in Javascript onAugust 25, 2010

(接上)先看张对老手不新鲜但对菜鸟很有趣的图:

Javascript new关键字的玄机 以及其它

What the heck is that? 简直是luan lun。

 

new

抛开上面的图,先看看上篇文章留下的第二个问题,让我们在构造器的函数体内加点东西,看会发生什么。

 

function A(){this.p = 1}
var a = new A()

会得到如下结果:

Javascript new关键字的玄机 以及其它

为什么用new关键字构造出来的a,会获得p这个属性?new A()这行代码做了什么事情?根据上篇文章中Function的创建过程第4步,A这个对象会有一个Construct属性(注意不是constructor,Consturct是ECMAScript标准里的属性,好像对外不可见),该属性的值是个函数,new A()即会调用A的这个Construct函数。那么这个Construct函数会做些啥呢?

1, 创建一个object,假设叫x。

2, 如果A.prototype是个object(一般都是),则把A.prototype赋给x.__proto__;否则(不常见),请大老板Object出马,把Object.prototype赋给x.__proto__。

3, 调用A.call(x),第一个参数传入我们刚刚创建的x。这就妥了,A的函数体里this.p = 1,这个this,就成了x。因此x就有了p这个属性,并且x.p = 1。

4, 一般情况下,就返回x了,这时a就是x了。但也有特殊情况,如果A的函数体里返回的东西,它的类型(typeof)是个object。那么a就不是指向x了,而是指向A函数返回的东西。

伪代码如下:

 

var x = new Object(); //事实上不一定用new来创建,我也不清楚。
x.__proto__ = A.prototype 
var result = A.call(x)
if (typeof(result) == "object"){
return result;
}
return x;

 

 

 

在我们的例子里,A函数返回undefined(因为没有return字眼),所以a就是x。但我们举个例子,验证下上面第4步里的特殊情况:

Javascript new关键字的玄机 以及其它

果然。

 

对象的constructor属性

再看看上篇文章留下的第一个问题

 

function Base(){}
Base.prototype.a = 1
var base = new Base();function Derived(){}
Derived.prototype = base;
var d = new Derived()

 

 

执行完上面的代码,mybase.constructor很容易猜到是Base,那么d.constructor呢?是Derived吗?

 Javascript new关键字的玄机 以及其它

不对,也是Base,怎么回事?很简单,复习下上篇的内容就知道:由于d本身没有constructor属性,所以会到d.__proto__上去找,d.__proto__就是Derived.prototype,也就是base这个对象,base也没constructor属性,于是再往上,到base.__proto__上找,也就是Base.prototype。它是有constructor属性的,就是Base本身。事实上,就我目前所知,只有构造器(function类型的object)的prototype,才真正自己拥有constructor属性的对象,且“构造器.prototype.constructor === 构造器”。

 

Instanceof

那么,instanceof怎么样?

Javascript new关键字的玄机 以及其它

从图中可以看出,d是Base、Derived和Object的实例。很合理,但这是怎么判断的呢?是这样的:对于x instanceof constructor的表达式,如果constructor.prototype在x的原型(__proto__)链里,那么就返回true。很显然,d的__proto__链往上依次是:Derived.prototype, Base.prototype, Object.prototype,得到图中结果就毫无疑问了。所以,instanceof跟对象的constructor属性无关。

 

Function and Object

最后解答一下文章开头的图。

Function和Object本身也是function类型的对象,因此可以说都是Function()构造出来的东西(自己构造自己,我不知道具体是不是这样,但就这么认为,挺合理的。)

也就是说,可以设想如下代码:

 

var Function = new Function()
var Object = new Function()

 

 

根据上篇文章的规律,会有Function.__proto__ === Function.prototype,以及Object.__proto__ === Function.prototype,验证一下:

Javascript new关键字的玄机 以及其它

Function instanceof Object,这是显然为true的,万物归Object管,Function的__proto__链依次指向:Function.prototype,Object.prototype。

Object instanceof Function,因为Function.prototype在Object的__proto__链中,所以也为true。

Javascript 相关文章推荐
URL编码转换,escape() encodeURI() encodeURIComponent()
Dec 27 Javascript
javascript 面向对象,实现namespace,class,继承,重载
Oct 29 Javascript
javascript调试之DOM断点调试法使用技巧分享
Apr 15 Javascript
JQuery调用WebServices的方法和4个实例
May 06 Javascript
使用jQuery实现星级评分代码分享
Dec 09 Javascript
javascript实现图片循环渐显播放的方法
Feb 24 Javascript
js中利用tagname和id获取元素的方法
Jan 03 Javascript
JS中改变this指向的方法(call和apply、bind)
Mar 26 Javascript
javascript数组常用方法汇总
Sep 10 Javascript
记一次vue去除#问题处理经过小结
Jan 24 Javascript
html-webpack-plugin修改页面的title的方法
Jun 18 Javascript
vue 避免变量赋值后双向绑定的操作
Nov 07 Javascript
jquery下组织javascript代码(js函数化)
Aug 25 #Javascript
jquery实现居中弹出层代码
Aug 25 #Javascript
jquery下实现overlay遮罩层代码
Aug 25 #Javascript
在网页中使用document.write时遭遇的奇怪问题
Aug 24 #Javascript
javascript下string.format函数补充
Aug 24 #Javascript
javascript下利用arguments实现string.format函数
Aug 24 #Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件
Aug 24 #Javascript
You might like
实现 win2003 下 mysql 数据库每天自动备份
2006/12/06 PHP
smarty section简介与用法分析
2008/10/03 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
2014/06/19 PHP
php获取根域名方法汇总
2014/10/28 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
漂亮的widgets,支持换肤和后期开发新皮肤(2007-4-27已更新1.7alpha)
2007/04/27 Javascript
jQuery对象和DOM对象的相互转化实现代码
2010/03/02 Javascript
jquery 元素控制(追加元素/追加内容)介绍及应用
2013/04/21 Javascript
JS将制定内容复制到剪切板示例代码
2014/02/11 Javascript
jQuery 无限级菜单的简单实例
2014/02/21 Javascript
js去除输入框中所有的空格和禁止输入空格的方法
2014/06/09 Javascript
教你如何自定义百度分享插件以及bshare分享插件的分享按钮
2014/06/20 Javascript
谈谈对offsetleft兼容性的理解
2015/11/11 Javascript
6种javascript显示当前系统时间代码
2015/12/01 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
React Router基础使用
2017/01/17 Javascript
解决node修改后需频繁手动重启的问题
2018/05/13 Javascript
Vuex的actions属性的具体使用
2019/04/14 Javascript
优化Vue中date format的性能详解
2020/01/13 Javascript
[02:16]DOTA2英雄基础教程 干扰者
2014/01/15 DOTA
Python实现快速傅里叶变换的方法(FFT)
2018/07/21 Python
Tensorflow加载预训练模型和保存模型的实例
2018/07/27 Python
python图像和办公文档处理总结
2019/05/28 Python
python3操作注册表的方法(Url protocol)
2020/02/05 Python
多个python文件调用logging模块报错误
2020/02/12 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
2020/03/09 Python
Python3安装模块报错Microsoft Visual C++ 14.0 is required的解决方法
2020/07/28 Python
用canvas实现图片滤镜效果附演示
2013/11/05 HTML / CSS
Canvas中设置width与height的问题浅析
2018/11/01 HTML / CSS
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
全球最大化妆品零售网站:SkinStore
2020/10/24 全球购物
南湾猴岛导游词
2015/02/09 职场文书
幼儿园教师暑期培训心得体会
2016/01/09 职场文书
职业规划从高考志愿专业选择开始
2019/08/08 职场文书
解决Pytorch dataloader时报错每个tensor维度不一样的问题
2021/05/28 Python
MySQL分布式恢复进阶
2022/07/23 MySQL