JavaScript中的 new 命令


Posted in Javascript onMay 22, 2019

面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。

那么,“对象”(object)到底是什么?

对象是单个实物的抽象。
对象是一个容器,封装了属性(property)和方法(method)。 属性是对象的状态,方法是对象的行为(完成某种任务)。

2. 构造函数

面向对象编程的第一步,就是要生成对象。通常需要一个模板,表示某一类实物的共同特征,然后对象根据这个模板生成。

JavaScript 语言使用构造函数(constructor)作为对象的模板。 “构造函数”,就是专门用来生成实例对象的函数。

它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。

var Vehicle = function () {
 this.price = 1000;
};

上面代码中, Vehicle 就是构造函数。为了与普通函数区别,构造函数名字的第一个字母通常大写。

构造函数的特点有两个。

this
new

3. new 命令

3.1 基本用法

3.1.1 new 的基本用法

new 命令的作用,就是执行构造函数,返回一个实例对象。

var Vehicle = function () {
 this.price = 1000;
};
var v = new Vehicle();
v.price // 1000

上面代码通过 new 命令,让构造函数 Vehicle 生成一个实例对象,保存在变量 v 中。 new 命令执行时,构造函数内部的 this ,就代表了新生成的实例对象, this.price 表示实例对象有一个 price 属性,值是1000。

下面两行代码是等价的,但是为了表示这里是函数调用, 推荐使用括号 。

// 推荐的写法
var v = new Vehicle();
// 不推荐的写法
var v = new Vehicle;

3.1.2 保证构造函数必须与 new 命令一起使用

如果忘了使用 new 命令,直接调用构造函数会发生什么事?

var Vehicle = function (){
 this.price = 1000;
};
var v = Vehicle();
v // undefined
price // 1000

上面代码中,调用 Vehicle 构造函数时,忘了加上 new 命令。结果,变量 v 变成了 undefined ,而 price 属性变成了全局变量。因此,应该非常小心,避免不使用 new 命令、直接调用构造函数。

为了保证构造函数必须与 new 命令一起使用,有2种解决办法:

构造函数内部使用严格模式,即第一行加上 use strict 。 这样的话,一旦忘了使用 new 命令,直接调用构造函数就会报错。

function Fubar(foo, bar){
 'use strict';
 this._foo = foo;
 this._bar = bar;
}
Fubar()
// TypeError: Cannot set property '_foo' of undefined

上面代码的 Fubar 为构造函数, use strict 命令保证了该函数在严格模式下运行。由于严格模式中,函数内部的 this 不能指向全局对象,默认等于 undefined ,导致不加 new 调用会报错(JavaScript 不允许对 undefined 添加属性)。

构造函数内部判断是否使用 new 命令,如果发现没有使用,则直接返回一个实例对象。

function Fubar(foo, bar) {
 if (!(this instanceof Fubar)) {
  return new Fubar(foo, bar);
 }
 this._foo = foo;
 this._bar = bar;
}
Fubar(1, 2)._foo // 1
(new Fubar(1, 2))._foo // 1

3.2 new 命令的原理

使用 new 命令时,它后面的函数依次执行下面的步骤。

prototype
this

也就是说,构造函数内部, this 指的是一个新生成的空对象,所有针对 this 的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即 this 对象),将其“构造”为需要的样子。

3.2.1 关于 return 语句

如果构造函数内部有 return 语句,而且 return 后面跟着一个对象, new 命令会返回 return 语句指定的对象;否则,就会不管 return 语句,返回 this 对象。

var Vehicle = function () {
 this.price = 1000;
 return 1000;
};
(new Vehicle()) === 1000
// false  new命令忽略了这个 return 语句,返回“构造”后的 this 对象。

如果 return 语句返回的是一个跟 this 无关的新对象, new 命令会返回这个新对象,而不是 this 对象。

var Vehicle = function (){
 this.price = 1000;
 return { price: 2000 };
};
(new Vehicle()).price
// 2000  new 命令返回这个对象,而不是 this 对象。

3.2.2 对普通函数使用 new

如果对普通函数(内部没有 this 关键字的函数)使用 new 命令,则会 返回一个空对象 。

function getMessage() {
 return 'this is a message';
}
var msg = new getMessage();
msg // {}
typeof msg // "object"

这是因为 new 命令总是返回一个对象,要么是实例对象,要么是 return 语句指定的对象。本例中, return 语句返回的是字符串,所以 new 命令就忽略了该语句。

Javascript 相关文章推荐
javascript String 的扩展方法集合
Jun 01 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
Apr 02 Javascript
jquery实现奇偶行赋值不同css值
Feb 17 Javascript
js隐藏与显示回到顶部按钮及window.onscroll事件应用
Jan 25 Javascript
js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?
Nov 18 Javascript
AngularJS转换响应内容
Jan 27 Javascript
全面了解函数声明与函数表达式、变量提升
Aug 09 Javascript
Bootstrap 表单验证formValidation 实现远程验证功能
May 17 Javascript
详解React+Koa实现服务端渲染(SSR)
May 23 Javascript
详解JavaScript中操作符和表达式
Sep 12 Javascript
vue开发环境配置跨域的方法步骤
Jan 16 Javascript
使用layui前端框架弹出form表单以及提交的示例
Oct 25 Javascript
element-ui组件中input等的change事件中传递自定义参数
May 22 #Javascript
原生JS实现列表内容自动向上滚动效果
May 22 #Javascript
小程序如何使用分包加载的实现方法
May 22 #Javascript
原生js实现trigger方法示例代码
May 22 #Javascript
koa router 多文件引入的方法示例
May 22 #Javascript
微信小程序template模板与component组件的区别和使用详解
May 22 #Javascript
微信小程序+腾讯地图开发实现路径规划绘制
May 22 #Javascript
You might like
Yii2中事务的使用实例代码详解
2016/09/07 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
php获取微信共享收货地址的方法
2017/12/21 PHP
PHP文件打开关闭及读写操作示例解析
2020/08/06 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
Prototype Hash对象 学习
2009/07/19 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮
2013/10/11 Javascript
yepnope.js使用详解及示例分享
2014/06/23 Javascript
jquery隔行换色效果实现方法
2015/01/15 Javascript
AngularJS学习笔记之ng-options指令
2015/06/16 Javascript
Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信
2017/02/23 Javascript
基于easyui checkbox 的一些操作处理方法
2017/07/10 Javascript
Vue.js的复用组件开发流程完整记录
2018/11/29 Javascript
jquery实现点击左右按钮切换图片
2021/01/27 jQuery
python中的五种异常处理机制介绍
2014/09/02 Python
Python的Tornado框架实现图片上传及图片大小修改功能
2016/06/30 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
多版本Python共存的配置方法
2017/05/22 Python
python-itchat 获取微信群用户信息的实例
2019/02/21 Python
基于Django实现日志记录报错信息
2019/12/17 Python
浅析Python面向对象编程
2020/07/10 Python
pycharm不以pytest方式运行,想要切换回普通模式运行的操作
2020/09/01 Python
python多线程爬取西刺代理的示例代码
2021/01/30 Python
CSS3实现大小不一的粒子旋转加载动画
2016/04/21 HTML / CSS
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
荷兰街头时尚之家:Funkie House
2019/03/18 全球购物
专升本自我鉴定
2013/10/10 职场文书
产品销售员岗位职责
2013/12/18 职场文书
文明家庭先进事迹材
2014/01/27 职场文书
网络文明传播志愿者活动方案
2014/08/20 职场文书
安全责任书范文
2014/08/25 职场文书
2015会计试用期工作总结
2014/12/12 职场文书
军训新闻稿范文
2015/07/17 职场文书
确保减税降费落地生根,用实实在在措施
2019/07/19 职场文书
tensorboard 可视化之localhost:6006不显示的解决方案
2021/05/22 Python