了解 JavaScript 构造函数

2023-05-16

以下是Faraz Kelhini的客座文章。其中一些东西超出了我的舒适区,所以我请凯尔辛普森为我进行技术检查。凯尔的回答(我们在办公时间会议期间所做的)非常有趣。它是:1)这篇文章在技术上是合理的。JavaScript 并没有传统意义上的类,这是大多数人硬塞进去的方式。2)我们可能想停止硬塞进去。JavaScript 有对象,我们可以按照它们的意图使用它们相同种类的东西。Kyle 称之为 OLOO(链接到其他对象的对象)。这是一个介绍。我认为两者都有学习的价值。

对构造函数有很好的理解对于真正理解 JavaScript 语言至关重要。从技术上讲,JavaScript 没有类,但它具有构造函数和原型,可以为 JavaScript 带来类似的功能。事实上,ES2015 中引入的类声明只是作为现有基于原型的继承的语法糖,并没有真正为语言添加任何额外的功能。

在本教程中,我们将详细探讨构造函数,并了解 JavaScript 如何利用它们来创建对象。

创建和使用构造函数

构造函数类似于常规函数,但我们将它们与new关键字一起使用。构造函数有两种类型:内置构造函数,例如ArrayObject,它们在运行时在执行环境中自动可用;和自定义构造函数,它们为您自己的对象类型定义属性和方法。

当您想要创建具有相同属性和方法的多个相似对象时,构造函数很有用。将构造函数的名称大写以将它们与常规函数区分开来是一种惯例。考虑以下代码:

function Book() { 
  // unfinished code
} 

var myBook = new Book();

代码的最后一行创建了一个实例Book并将其分配给一个变量。尽管Book构造函数没有做任何事情,myBook但仍然是它的一个实例。如你所见,这个函数和普通函数没有什么区别,只是它是用new关键字调用的,而且函数名是大写的。

确定实例的类型

要确定一个对象是否是另一个对象的实例,我们使用instanceof运算符:

myBook instanceof Book    // true
myBook instanceof String  // false

请注意,如果运算符的右侧instanceof不是函数,则会抛出错误:

myBook instanceof {};
// TypeError: invalid 'instanceof' operand ({})

另一种查找实例类型的方法是使用constructor属性。考虑以下代码片段:

myBook.constructor === Book;   // true

myBook指向的构造函数属性Book,所以严格相等运算符返回true。JavaScript 中的每个对象都constructor从其原型继承一​​个属性,该属性指向创建该对象的构造函数:

var s = new String("text");
s.constructor === String;      // true

"text".constructor === String; // true

var o = new Object();
o.constructor === Object;      // true

var o = {};
o.constructor === Object;      // true

var a = new Array();
a.constructor === Array;       // true

[].constructor === Array;      // true

但是请注意,使用该constructor属性检查实例的类型通常被认为是不好的做法,因为它可以被覆盖。

自定义构造函数

构造函数就像一个千篇一律的工具,用于制作具有相同属性和方法的多个对象。考虑以下示例:

function Book(name, year) {
  this.name = name;
  this.year = '(' + year + ')';
}

构造Book函数需要两个参数:nameyear。使用new关键字调用构造函数时,会将接收到的参数赋值给当前实例的nameandyear属性,如下图:

var firstBook = new Book("Pro AngularJS", 2014);
var secondBook = new Book("Secrets Of The JavaScript Ninja", 2013); 
var thirdBook = new Book("JavaScript Patterns", 2010);
 
console.log(firstBook.name, firstBook.year);           
console.log(secondBook.name, secondBook.year);           
console.log(thirdBook.name, thirdBook.year);  

Book如您所见,我们可以通过调用具有不同参数的构造函数来快速构建大量不同的书籍对象。这与 JavaScript 在其内置构造函数(如Array()和)中使用的模式完全相同Date()

Object.defineProperty() 方法

Object.defineProperty()方法可以在构造函数中使用,以帮助执行所有必要的属性设置。考虑以下构造函数:

function Book(name) { 
  Object.defineProperty(this, "name", { 
      get: function() { 
        return "Book: " + name;       
      },        
      set: function(newName) {            
        name = newName;        
      },               
      configurable: false     
   }); 
}

var myBook = new Book("Single Page Web Applications");
console.log(myBook.name);    // Book: Single Page Web Applications

// we cannot delete the name property because "configurable" is set to false
delete myBook.name;    
console.log(myBook.name);    // Book: Single Page Web Applications

// but we can change the value of the name property
myBook.name = "Testable JavaScript";
console.log(myBook.name);    // Book: Testable JavaScript

此代码用于Object.defineProperty()定义访问器属性。访问器属性不包括任何属性或方法,但它们定义了读取属性时要调用的 getter,以及写入属性时要调用的 setter。

getter 应该返回一个值,而 setter 接收分配给属性的值作为参数。上面的构造函数返回一个实例,其name属性可以设置或更改,但不能删除。当我们得到 的值时name,getter 将字符串附加Book:到名称并返回它。

对象字面量表示法优于构造函数

JavaScript 语言有九个内置构造函数:Object()Array()String()Number()Boolean()Date()Function(),Error()RegExp(). 创建值时,我们可以自由使用对象字面量或构造函数。然而,对象字面量不仅更易于阅读,而且运行速度更快,因为它们可以在解析时进行优化。因此,对于简单的对象,最好坚持使用文字:

// a number object
// numbers have a toFixed() method
var obj = new Object(5);
obj.toFixed(2);     // 5.00

// we can achieve the same result using literals
var num = 5;
num.toFixed(2);     // 5.00

// a string object
// strings have a slice() method 
var obj = new String("text");
obj.slice(0,2);     // "te"

// same as above
var string = "text";
string.slice(0,2);  // "te"

如您所见,对象字面量和构造函数之间几乎没有任何区别。更有趣的是,仍然可以在文字上调用方法。当对文字调用方法时,JavaScript 会自动将文字转换为临时对象,以便该方法可以执行操作。一旦不再需要临时对象,JavaScript 就会丢弃它。

使用 new 关键字是必不可少的

重要的是要记住new在所有构造函数之前使用关键字。如果您不小心忘记了new,您将修改全局对象而不是新创建的对象。考虑以下示例:

function Book(name, year) {
  console.log(this);
  this.name = name;
  this.year = year;
}

var myBook = Book("js book", 2014);  
console.log(myBook instanceof Book);  
console.log(window.name, window.year);

var myBook = new Book("js book", 2014);  
console.log(myBook instanceof Book);  
console.log(myBook.name, myBook.year);

当我们在Book没有 的情况下调用构造函数时new,实际上是在调用没有返回语句的函数。结果,this在构造函数内部指向Window(而不是myBook),并创建了两个全局变量。但是,当我们用 调用函数时new,上下文会从全局(窗口)切换到实例。所以,this正确地指向myBook

请注意,在严格模式下,此代码会引发错误,因为严格模式旨在防止程序员意外调用没有new关键字的构造函数。

范围安全的构造函数

正如我们所见,构造函数只是一个函数,因此可以在没有new关键字的情况下调用它。但是,对于没有经验的程序员来说,这可能是错误的来源。范围安全的构造函数旨在返回相同的结果,无论是否调用new它,它都不会受到这些问题的影响。

大多数内置构造函数,例如和Object,都是范围安全的。他们使用一种特殊的模式来确定如何调用构造函数。如果不使用,它们会通过再次调用构造函数来返回对象的正确实例。考虑以下代码:RegexArraynewnew

function Fn(argument) { 

  // if "this" is not an instance of the constructor
  // it means it was called without new  
  if (!(this instanceof Fn)) { 

    // call the constructor again with new
    return new Fn(argument);
  } 
}

因此,我们的构造函数的作用域安全版本将如下所示:

function Book(name, year) { 
  if (!(this instanceof Book)) { 
    return new Book(name, year);
  }
  this.name = name;
  this.year = year;
}

var person1 = new Book("js book", 2014);
var person2 = Book("js book", 2014);

console.log(person1 instanceof Book);    // true
console.log(person2 instanceof Book);    // true

结论

重要的是要理解 ES2015 中引入的类声明只是作为现有基于原型的继承的语法糖,并没有向 JavaScript 添加任何新内容。构造函数和原型是 JavaScript 定义相似和相关对象的主要方式。

在本文中,我们很好地了解了 JavaScript 构造函数的工作原理。我们了解到构造函数类似于常规函数,但它们与new关键字一起使用。我们看到了构造函数如何使我们能够快速创建具有相同属性和方法的多个相似对象,以及为什么instanceof操作符是确定实例类型的最安全方法。最后,我们查看了范围安全的构造函数,可以使用或不使用new.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 JavaScript 构造函数 的相关文章

随机推荐

  • 字符设备驱动-linux驱动开发第3部分-朱有鹏-专题视频课程

    字符设备驱动 linux驱动开发第3部分 4561人已学习 课程介绍 本课程是linux驱动开发的第3个课程 xff0c 接上部分继续讲解字符设备驱动的开发要点 xff0c 重点是相关的内核源代码的解析和一些真正驱动惯用的编程手法的引入 本
  • C++测试代码运行时间

    如果我们想直观地看出朴素算法和其他算法对程序运行时间的影响 xff0c 那么就可以采取以下方式 方法1 xff1a 基于头文件ctime和函数clock 的实现 代码1 xff1a include lt iostream gt includ
  • VMware虚拟机安装CentOS 7

    目录 1 VMware软件安装 2 CentOS 7 镜像下载 3 VMware安装CentOS 1 安装前内容设置 xff1a 2 安装中操作步骤 3 安装后语言设置 4 将图形化界面切换为命令符界面 如何联系我 xff1f wei ha
  • 解决Windows开机后无启动项的问题

    前言 为什么会出现这个问题 xff1f 此前PC上装有Windows 43 Ubuntu双系统 xff0c 由于又配置了虚拟机下的Centos xff0c 我把Ubuntu系统卸载了 没想到手滑删除了Windows的引导项 如图所示 xff
  • KMP算法图文详解

    简介 xff1a Knuth Morris Pratt xff08 KMP算法or字符串查找算法 xff09 可在一较长串S内查找一子串P出现的位置 xff0c KMP算法利用最长公共前后缀的特性以避免重新检索先前配对的字符串 xff0c
  • 离散数学期末习题

    前言 xff1a 本文适用于应对HUEL离散数学 期末考试 xff0c 重点整理了HUEL离散数学 期末考试范围内的题型 xff0c 既可以应对HUEL离散数学期末考试 xff0c 亦可以作为数据结构与算法的预备知识 如何联系我 xff1f
  • VMware Tools在Centos 7环境的安装教程

    前言 xff1a 阅读本文 xff0c 您可以得到 xff1a VMware Tools在Centos7环境下的安装步骤 xff1b 正文 xff1a VMware Tools在Centos7环境下安装步骤 xff1b 1 您需要保持虚拟机
  • 宝塔面板快速部署SSL证书

    前言 xff1a 发现自己的网站不能使用https访问 xff0c 原来是没有为网站部署SSL证书 通过本文 xff0c 您可以一键免费部署SSL证书 xff08 Let 39 s Encrypt xff09 正文 xff1a 1 如图显示
  • 宝塔面板部署WordPress(保姆式教程)

    前言 xff1a 通过本篇文章 xff0c 您可以掌握 xff1a 1 基于宝塔面板的快速建站操作 xff1b 2 一些浅浅的建站知识与技能 xff1b 3 WordPress助您快速建站 xff0c 节省您的时间 xff1b 如何联系我
  • VS 2022 C++ 自定义头文件示例

    前言 xff1a 博主最近刚从VS Code转到VS 2022 xff0c 但发现自定义的方法和VS Code有些不同 xff0c 故出一期VS 2022自定义头文件的博客 xff0c 时间仓促 xff0c 请不吝赐教 如何联系我 xff1
  • 零基础搭建网站(保姆级教程)

    前言 xff1a 本教程不需要任何前置知识 xff0c 零基础教您搭建网站 如何联系我 xff1f wei haoran 64 outlook com 正文 xff1a 搭建网站需要什么 xff1f 1 域名 xff1b 2 服务器 xff
  • 驱动框架入门之LED-linux驱动开发第4部分-朱有鹏-专题视频课程

    驱动框架入门之LED linux驱动开发第4部分 5199人已学习 课程介绍 本课程是linux驱动开发的第4个课程 xff0c 主要内容是驱动框架的引入 通过led驱动框架和gpiolib的这两个框架的详细解释 xff0c 让大家学习内核
  • VSCode远程连接服务器(SSH免密登录)

    前文 连接远程服务器的方式众多 xff0c 本文将介绍基于VS Code的SSH免密登录方法 在开始SSH远程链接以前 xff0c 您需要完成以下步骤 xff1a 1 Windows配置SSH xff1a 1 以Windows平台为例 xf
  • Linux云服务器防止暴力破解(三道SSH安全策略)

    前言 新购入的服务器 xff0c 往往用户名默认为root xff0c ssh默认开放22端口 xff0c 且配置SSH服务时往往同时允许密码和公钥二重登录 然而 xff0c 许多非法服务器运行着暴力破解程序 xff0c 通过访问用户名ro
  • Git快速入门(图文教程)

    前言 xff1a Git是目前最流行的版本控制工具之一 xff0c 它可以帮助我们更好地管理代码 xff0c 协作开发 xff0c 以及保证代码的安全性 在学习Git之前 xff0c 我们需要先了解几个概念 xff1a workspace
  • VS Code + phpstudy实现PHP环境配置

    概述 xff1a 要使用VSCode进行PHP开发 xff0c 需要先在本地搭建PHP环境 xff0c 并将其配置到VSCode中 下面是具体的步骤 xff1a 1 下载安装PHPStudy 首先 xff0c 我们需要从PHPStudy官网
  • CSS圆角边框

    设置css圆角边框 1 border radius 属性用于向元素添加圆角边框 css圆角边框代码 xff1a border radius 15px 2 对应四个角 xff0c CSS3提供四个单独的属性 xff1a border top
  • CSS渐变色

    渐变 xff1a 通过渐变可以设置一些复杂的背景颜色 xff0c 可以从实现一个颜色向其他颜色过渡的效果 渐变是图片 xff0c 通过 background image设置 CSS 定义了两种渐变类型 xff1a 线性渐变 xff08 向下
  • js的for循环语句

    For循环语法 xff1a for 循环是在您希望创建循环时经常使用的工具 for 循环的语法如下 xff1a for 语句 1 语句 2 语句 3 要执行的代码块 语句 1 在循环 xff08 代码块 xff09 开始之前执行 语句 2
  • 了解 JavaScript 构造函数

    以下是Faraz Kelhini的客座文章 其中一些东西超出了我的舒适区 xff0c 所以我请凯尔辛普森为我进行技术检查 凯尔的回答 xff08 我们在办公时间会议期间所做的 xff09 非常有趣 它是 xff1a 1 xff09 这篇文章