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 相关文章推荐
让插入到 innerHTML 中的 script 跑起来的实现代码
Jul 01 Javascript
JQuery for与each性能比较分析
May 14 Javascript
JS+DIV实现鼠标划过切换层效果的方法
May 25 Javascript
js实现发送验证码后的倒计时功能
May 28 Javascript
关于网页中的无缝滚动的js代码
Jun 09 Javascript
解决微信内置浏览器返回上一页强制刷新问题方法
Feb 05 Javascript
从零开始学习Node.js系列教程三:图片上传和显示方法示例
Apr 13 Javascript
JS SetInterval 代码实现页面轮询
Aug 11 Javascript
Angular8路由守卫原理和使用方法
Aug 29 Javascript
vue-froala-wysiwyg 富文本编辑器功能
Sep 19 Javascript
在vue中created、mounted等方法使用小结
Jul 21 Javascript
JavaScript实现打字游戏
Feb 19 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实现无限级分类
2014/12/24 PHP
WordPress中获取指定分类及其子分类下的文章数目
2015/12/31 PHP
PHP简单判断字符串是否包含另一个字符串的方法
2016/03/25 PHP
XHProf报告字段含义的解析
2016/05/17 PHP
php自定义函数转换html标签示例
2016/09/29 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
php实现多维数组排序的方法示例
2017/03/23 PHP
PHP简单验证码功能机制实例详解
2019/03/27 PHP
JavaScript闭包函数访问外部变量的方法
2014/08/27 Javascript
jQuery简单实现验证邮箱格式
2015/07/15 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
JS中mouseover和mouseout多次触发问题如何解决
2016/06/06 Javascript
打造自己的jQuery插件入门教程
2016/09/23 Javascript
js中编码函数:escape,encodeURI与encodeURIComponent详解
2017/03/21 Javascript
浅谈jquery fullpage 插件增加头部和版权的方法
2018/03/20 jQuery
JS/jQuery实现简单的开关灯效果【案例】
2019/02/19 jQuery
Javascript前端下载后台传来的文件流代码实例
2020/08/18 Javascript
[07:06]2018DOTA2国际邀请赛寻真——卫冕冠军Team Liquid
2018/08/10 DOTA
python字符串替换示例
2014/04/24 Python
Python中random模块用法实例分析
2015/05/19 Python
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
python:动态路由的Flask程序代码
2019/11/22 Python
Python计算IV值的示例讲解
2020/02/28 Python
在家更换处方镜片:Lensabl
2019/05/01 全球购物
怎样写留学自荐信
2013/11/11 职场文书
创先争优活动方案
2014/02/12 职场文书
房产委托公证书样本
2014/04/04 职场文书
酒店开业庆典策划方案
2014/05/28 职场文书
移交协议书
2014/08/19 职场文书
2014年教师节国旗下讲话稿
2014/09/10 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
大雁塔英文导游词
2015/02/10 职场文书
2016年12月份红领巾广播稿
2015/12/21 职场文书
加强党性修养心得体会
2016/01/21 职场文书
Python实现仓库管理系统
2022/05/30 Python