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 相关文章推荐
超级简单的图片防盗(HTML),好用
Apr 08 Javascript
javascript SocialHistory 检查访问者是否访问过某站点
Aug 02 Javascript
js以对象为索引的关联数组
Jul 04 Javascript
jquery如何把参数列严格转换成数组实现思路
Apr 01 Javascript
js图片轮播效果实现代码
Apr 18 Javascript
javascript 操作cookies详解及实例
Feb 22 Javascript
vue多种弹框的弹出形式的示例代码
Sep 18 Javascript
详解Chai.js断言库API中文文档
Jan 31 Javascript
JQuery模拟实现网页中自定义鼠标右键菜单功能
Nov 14 jQuery
Next.js项目实战踩坑指南(笔记)
Nov 29 Javascript
Vue项目history模式下微信分享爬坑总结
Mar 29 Javascript
Vue移动端实现图片上传及超过1M压缩上传
Dec 23 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
PHP7生产环境队列Beanstalkd用法详解
2020/05/19 PHP
JS遮罩层效果 兼容ie firefox jQuery遮罩层
2010/07/26 Javascript
javascript替换已有元素replaceChild()使用介绍
2014/04/03 Javascript
jquery幻灯片插件bxslider样式改进实例
2014/10/15 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
页面向下滚动ajax获取数据的实现方法(兼容手机)
2016/05/24 Javascript
Ubuntu系统下Angularjs开发环境安装
2016/09/01 Javascript
vue监听滚动事件实现滚动监听
2017/04/11 Javascript
浅谈Angular2 模块懒加载的方法
2017/10/04 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
2017/12/12 Javascript
vue绑定的点击事件阻止冒泡的实例
2018/02/08 Javascript
vue2.0 自定义 饼状图 (Echarts)组件的方法
2018/03/02 Javascript
vuex操作state对象的实例代码
2018/04/25 Javascript
Jquery $.map使用方法实例详解
2020/09/01 jQuery
python判断字符串是否包含子字符串的方法
2015/03/24 Python
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
详解分布式任务队列Celery使用说明
2018/11/29 Python
Python之使用adb shell命令启动应用的方法详解
2019/01/07 Python
PyQt QListWidget修改列表项item的行高方法
2019/06/20 Python
PyQt QCombobox设置行高的方法
2019/06/20 Python
python celery分布式任务队列的使用详解
2019/07/08 Python
Python面向对象中类(class)的简单理解与用法分析
2020/02/21 Python
python实现企业微信定时发送文本消息的示例代码
2020/11/24 Python
荷兰家电销售网站:Welhof
2020/12/08 全球购物
大学生职业规划论文
2014/01/11 职场文书
学校安全教育月活动总结
2014/07/07 职场文书
2014教师党员个人自我评议
2014/09/20 职场文书
小学教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
旅行社计调工作总结
2015/08/12 职场文书
2016天猫双十一广告语
2016/01/28 职场文书
IDEA 链接Mysql数据库并执行查询操作的完整代码
2021/05/20 MySQL
Spring Boot两种全局配置和两种注解的操作方法
2021/06/29 Java/Android
Golang 切片(Slice)实现增删改查
2022/04/22 Golang
OpenFeign实现远程调用
2022/08/14 Java/Android