javascript中new关键字详解


Posted in Javascript onDecember 14, 2015

和其他高级语言一样javascript中也有new关键字,我们以前认知的new是用来创建一个类的实例对象,但在js中万物皆是对象,为何还要new关键字呢,其实js中new关键字不是用来创建一个类的实例对象,而是用于继承。 接下来,本文将带你一起来探索JS中new的奥秘...

function Animal(name){
  this.name = name;
}
Animal.color = "black";
Animal.prototype.say = function(){
  console.log("I'm " + this.name);
};
var cat = new Animal("cat");

console.log(
  cat.name, //cat
  cat.height //undefined
);
cat.say(); //I'm cat

console.log(
  Animal.name, //Animal
  Animal.color //back
);
Animal.say(); //Animal.say is not a function

如果你能理解上面输出的结果,说明你已非常了解js中new和this的运行机制,请忽略本文!

我们将通过解析这个例子来加深你对js中new和继承的理解! 【如果你对js的this还不了解,请先阅读:JS作用域和this关键字】

一、代码解读

  1-3行创建了一个函数Animal,并在其this上定义了属性:name,name的值是函数被执行时的形参。

  第4行在Animal对象(Animal本身是一个函数对象)上定义了一个静态属性:color,并赋值“black”

  5-7行在Animal函数的原型对象prototype上定义了一个say()方法,say方法输出了this的name值。

  第8行通过new关键字创建了一个新对象cat

  10-14行cat对象尝试访问name和color属性,并调用say方法。

  16-20行Animal对象尝试访问name和color属性,并调用say方法。

二、重点解析

  第8行代码是关键:

var cat = new Animal("cat");

 JS引擎在执行这句代码时,做了很多工作,用伪代码模拟其工作流程如下:

var obj = {};
 obj.__proto__ = Animal.prototype;
 var result = Animal.call(obj,"cat");
 return typeof result === 'obj'? result : obj;

(1)创建一个空对象obj;

(2)把obj的__proto__ 指向Animal的原型对象prototype,此时便建立了obj对象的原型链:obj->Animal.prototype->Object.prototype->null

      【如果你不了解JS原型链,请先阅读:JS原型和原型链】

(3)在obj对象的执行空间调用Animal函数并传递参数“cat”。 相当于var result = obj.Animal("cat")。

       当这句执行完之后,obj便产生了属性name并赋值为"cat"。【关于JS中call的用法请阅读:JS的call和apply】

(4)考察第3步返回的返回值,如果无返回值或者返回一个非对象值,则将obj返回作为新对象;否则会将返回值作为新对象返回。

了解了new的运行机制后,我们知道cat其实就是过程(4)的返回值,因此我们对cat对象的认知就多了一些:

cat的原型链是:obj->Animal.prototype->Object.prototype->null

cat上新增了一个属性:name

分析完了cat的产生过程,我们再看看输出结果:

cat.name -> 在过程(3)中,obj对象就产生了name属性。因此cat.name就是这里的obj.name

cat.color -> cat会先查找自身的color,没有找到便会沿着原型链查找,在上述例子中,我们仅在Animal对象上定义了color,并没有在其原型链上定义,因此找不到。

cat.say -> cat会先查找自身的say方法,没有找到便会沿着原型链查找,在上述例子中,我们在Animal的prototype上定义了say,因此在原型链上找到了say方法。

另外,在say方法中还访问this.name,这里的this指的是其调用者obj,因此输出的是obj.name的值。

对于Animal来说,它本身也是一个对象,因此,它在访问属性和方法时也遵守上述查找规则,所以:

Animal.color -> "black"

Animal.name -> "Animal" , Animal先查找自身的name,找到了name,注意:但这个name不是我们定义的name,而是函数对象内置的属性。

一般情况下,函数对象在产生时会内置name属性并将函数名作为赋值(仅函数对象)。

Animal.say -> Animal在自身没有找到say方法,也会沿着其原型链查找,话说Animal的原型链是什么呢?

javascript中new关键字详解

 从调试结果看:Animal的原型链是这样的:

 Animal->Function.prototype->Object.prototype->null

 因此Animal的原型链上没有定义say方法!

 总结一下,javascript的new关键字主要的作用是继承,上面例子中,cat对象在产生时便继承了Animal中定义的方法和属性,因此cat不是Animal的实例而是其子类(不严谨的说法)。可能有人还会想:cat既然是new出来的,那cat和Animal应该是同类型的。我认为既然是父类和子类的关系,那就不可能是同类型,不信,你看:

javascript中new关键字详解

javascript 使用new关键字的区别

第一种方式使用new关键字以原型的方式将user对象暴露到window对象中

//one
var user = function(){
  this.name="";
  this.id="";
};
user.add = function(){
  console.log("add");
};
user.delete = function(){
  console.log("delete");
};
user.prototype = user;
window.user = new user();

第二种方式不使用new关键字直接将user对象暴露到window对象中

//two
var user = {
  name:"",
  id:""
};
user.add = function(){
  console.log("add");
};
user.delete = function(){
  console.log("delete");
};
window.user = user;

使用

<button onclick="user.add()">增加</button>
<button onclick="user.delete()">删除</button>
Javascript 相关文章推荐
让innerHTML的脚本也可以运行起来
Jul 01 Javascript
用JavaScript对JSON进行模式匹配(Part 1-设计)
Jul 17 Javascript
JQuery文本改变触发事件如聚焦事件、失焦事件
Jan 15 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
May 28 Javascript
node.js中的buffer.slice方法使用说明
Dec 10 Javascript
jQuery EasyUI Tab 选项卡问题小结
Aug 16 Javascript
Jquery Easyui搜索框组件SearchBox使用详解(19)
Dec 17 Javascript
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
Oct 17 Javascript
angularJS自定义directive之带参方法传递详解
Oct 09 Javascript
vue实现多组关键词对应高亮显示功能
Jul 25 Javascript
微信小程序实现定位及到指定位置导航的示例代码
Aug 20 Javascript
使用PDF.js渲染canvas实现预览pdf的效果示例
Apr 17 Javascript
jQuery position() 函数详解以及jQuery中position函数的应用
Dec 14 #Javascript
Position属性之relative用法
Dec 14 #Javascript
CSS中position属性之fixed实现div居中
Dec 14 #Javascript
通过设置CSS中的position属性来固定层的位置
Dec 14 #Javascript
js实现拖拽效果(构造函数)
Dec 14 #Javascript
jQuery滚动加载图片实现原理
Dec 14 #Javascript
jQuery点击按钮弹出遮罩层且内容居中特效
Dec 14 #Javascript
You might like
php实现cc攻击防御和防止快速刷新页面示例
2014/02/13 PHP
php检索或者复制远程文件的方法
2015/03/13 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
2015/07/03 PHP
PHP汉字转换拼音的函数代码
2015/12/30 PHP
PHP随机数 C扩展随机数
2016/05/04 PHP
php获取文件名称和扩展名的方法
2017/02/07 PHP
javascript中Date对象的getDay方法使用指南
2014/12/22 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
2015/11/02 Javascript
基于jQuery实现二级下拉菜单效果
2016/02/01 Javascript
你真的了解BOM中的history对象吗
2017/02/13 Javascript
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
详解ES6 CLASS在微信小程序中的应用实例
2020/04/24 Javascript
Vue如何实现监听组件原生事件
2020/07/03 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
[00:12]2018DOTA2亚洲邀请赛 sylar表现SOLO技艺
2018/04/06 DOTA
python实现简单点对点(p2p)聊天
2017/09/13 Python
Python scikit-learn 做线性回归的示例代码
2017/11/01 Python
Python实现可获取网易页面所有文本信息的网易网络爬虫功能示例
2018/01/15 Python
Python 解决OPEN读文件报错 ,路径以及r的问题
2019/12/19 Python
利用pandas向一个csv文件追加写入数据的实现示例
2020/04/23 Python
Python如何使用队列方式实现多线程爬虫
2020/05/12 Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
2020/06/02 Python
详解Python IO编程
2020/07/24 Python
39美元购买一副眼镜或太阳镜:39DollarGlasses.com
2018/06/17 全球购物
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
教师实习期自我鉴定
2013/10/06 职场文书
小学生演讲稿
2014/01/12 职场文书
高中生自我评语大全
2014/01/19 职场文书
接待员岗位责任制
2014/02/10 职场文书
工作岗位说明书模板
2014/05/09 职场文书
优秀的应届生自荐信
2014/05/23 职场文书
小学生春游活动方案
2014/08/20 职场文书
婚宴祝酒词大全
2015/08/10 职场文书
环保建议书作文300字
2015/09/14 职场文书
工人先锋号事迹材料(2016精选版)
2016/03/01 职场文书
mysql拆分字符串作为查询条件的示例代码
2022/07/07 MySQL