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 相关文章推荐
ExtJs 3.1 XmlTreeLoader Example Error
Feb 09 Javascript
JavaScript 开发规范要求(图文并茂)
Jun 11 Javascript
jQuery学习笔记之jQuery的事件
Dec 22 Javascript
jQuery操作Select选择的Text和Value(获取/设置/添加/删除)
Mar 06 Javascript
js 获取class的元素的方法 以及创建方法getElementsByClassName
Mar 11 Javascript
js 调用父窗口的具体实现代码
Jul 15 Javascript
jquery animate实现鼠标放上去显示离开隐藏效果
Jul 21 Javascript
JavaSacript中charCodeAt()方法的使用详解
Jun 05 Javascript
JavaScript电子时钟倒计时
Jan 09 Javascript
jQuery+CSS3+Html5实现弹出层效果实例代码(附源码下载)
May 16 Javascript
JS短信验证码倒计时功能的实现(没有验证码,只有倒计时)
Oct 27 Javascript
微信小程序开发数据缓存基础知识辨析及运用实例详解
Nov 06 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
php feof用来识别文件末尾字符的方法
2010/08/01 PHP
用Json实现PHP与JavaScript间数据交换的方法详解
2013/06/20 PHP
javascript 函数式编程
2007/08/16 Javascript
ajax页面无刷新 IE下遭遇Ajax缓存导致数据不更新的问题
2012/12/11 Javascript
Knockout数组(observable)使用详解示例
2013/11/15 Javascript
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
纯js代码制作的网页时钟特效【附实例】
2016/03/30 Javascript
第九章之路径分页标签与徽章组件
2016/04/25 Javascript
Bootstrap每天必学之工具提示(Tooltip)插件
2016/04/26 Javascript
JS判断键盘是否按的回车键并触发指定按钮点击操作的方法
2017/02/13 Javascript
无循环 JavaScript(map、reduce、filter和find)
2017/04/08 Javascript
[js高手之路]HTML标签解释成DOM节点的实现方法
2017/08/31 Javascript
vue+vuecli+webpack中使用mockjs模拟后端数据的示例
2017/10/24 Javascript
基于Vue实现拖拽效果
2018/04/27 Javascript
jQuery实现模糊搜索功能的方法分析
2018/06/29 jQuery
解决vue打包css文件中背景图片的路径问题
2018/09/03 Javascript
小程序云开发获取不到数据库记录的解决方法
2019/05/18 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
2019/05/30 Javascript
原生js实现五子棋游戏
2020/05/28 Javascript
Vue $emit()不能触发父组件方法的原因及解决
2020/07/28 Javascript
Openlayers实现点闪烁扩散效果
2020/09/24 Javascript
python实现dict版图遍历示例
2014/02/19 Python
浅谈python中的变量默认是什么类型
2016/09/11 Python
Python 处理数据的实例详解
2017/08/10 Python
python使用pyqt写带界面工具的示例代码
2017/10/23 Python
ubuntu16.04制作vim和python3的开发环境
2018/09/23 Python
Python3 翻转二叉树的实现
2019/09/30 Python
Python3与fastdfs分布式文件系统如何实现交互
2020/06/23 Python
利用css3-animation实现逐帧动画效果
2016/03/10 HTML / CSS
表彰大会主持词
2014/03/26 职场文书
协议书样本
2014/04/23 职场文书
计划生育宣传标语
2014/06/21 职场文书
退休党员个人对照检查材料思想汇报
2014/09/29 职场文书
乔布斯辞职信(中英文对照)
2015/05/12 职场文书
Python中相见恨晚的技巧
2021/04/13 Python
Python面向对象之成员相关知识总结
2021/06/24 Python