资讯专栏INFORMATION COLUMN

JavaScript之 new 命令

desdik / 2197人阅读

摘要:命令执行时,构造函数内部的,就代表了新生成的实例对象,表示实例对象有一个属性,值是。因此,应该非常小心,避免不使用命令直接调用构造函数。命令返回这个对象,而不是对象。

JavaScript 面向对象编程的基础知识篇 1 。

1. 概述

面向对象编程(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 教程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/6932.html

相关文章

  • 温故知新javascript面向对象

    摘要:应该非常小心,避免出现不使用命令直接调用构造函数的情况。上面代码表示,使用属性,确定实例对象的构造函数是,而不是。当然,从继承链来看,只有一个父类,但是由于在的实例上,同时执行和的构造函数,所以它同时继承了这两个类的方法。 基本概念 类和实例是大多数面向对象编程语言的基本概念 类:类是对象的类型模板 实例:实例是根据类创建的对象但是,JavaScript语言的对象体系,不是基于类的,...

    赵连江 评论0 收藏0
  • 再遇设计模式JavaScript

    摘要:在面向对象的语言中,比如,等,单例模式通常是定义类时将构造函数设为,保证对象不能在外部被出来,同时给类定义一个静态的方法,用来获取或者创建这个唯一的实例。 万事开头难,作为正经历菜鸟赛季的前端player,已经忘记第一次告诉自己要写一些东西出来是多久以的事情了。。。如果,你也和我一样,那就像我一样,从现在开始,从看到这篇文章开始,打开电脑,敲下你的第一篇文章(或者任何形式的文字)吧。 ...

    Clect 评论0 收藏0
  • 细谈JavaScript中的一些设计模式

    摘要:注意事项声明函数时候处理业务逻辑区分和单例的区别,配合单例实现初始化构造函数大写字母开头推荐注意的成本。简单工厂模式使用一个类通常为单体来生成实例。 @(书籍阅读)[JavaScript, 设计模式] 常见设计模式 一直对设计模式不太懂,花了一下午加一晚上的时间,好好的看了看各种设计模式,并总结了一下。 设计模式简介 设计模式概念解读 设计模式的发展与在JavaScript中的应用 ...

    30e8336b8229 评论0 收藏0
  • JS原型与原型链

    摘要:因此,就会形成一个原型链对象到原型,再到原型的原型如果一层层地上溯,所有对象的原型最终都可以上溯到,即构造函数的属性。 对于很多前端开发者而言,JavaScript中原型与原型链是一个比较容易疑惑的点,所以本文记录了自己对应这方面的一点理解,以后有更深的理解再来更新。 对象 想要了解原型与原型链,首先要了解什么是对象?面向对象编程(Object Oriented Programmin...

    Fourierr 评论0 收藏0
  • 在 Laravel 项目中使用 Glup Laravel-Elixir

    摘要:结果会被存放到拷贝文件目录你可以使用方法拷贝文件目录到新路径,所有操作都相对于项目根目录版本号缓存刷新很多开发者会给编译的前端资源添加时间戳或者唯一令牌后缀以强制浏览器加载最新版本而不是代码的缓存副本。 环境准备 1、安装 nodejs 和 npm  如果你使用的是 Laravel 的 Homestead 环境,可以不用安装了,已自带。  我们来查看下它们的版本: $ node -v ...

    ralap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<