JavaScript指南第3部分:变量,数据类型,表达式,对象

今天,在JavaScript手册的翻译的第三部分中,我们将讨论声明变量的不同方法,数据类型,表达式以及使用对象的功能。

第1部分:第一个程序,语言功能,标准
第2部分:代码样式和程序结构
第3部分:变量,数据类型,表达式,对象
第4部分:功能
第5部分:数组和循环
第6部分:异常,分号,通配符文字
第7部分:严格模式,此关键字,事件,模块,数学计算
第8部分:ES6功能概述
第9部分:ES7,ES8和ES9标准概述



变数


变量是分配了值的标识符。 可以在程序中访问变量,以这种方式使用为其分配的值。

JavaScript本身的变量不包含有关将存储在其中的值类型的信息。 这意味着通过写入变量(例如字符串),以后可以在其中写入数字。 这样的操作不会引起程序错误。 因此,JavaScript有时被称为“非类型化”语言。

在使用变量之前,必须使用varlet关键字对其进行声明。 当涉及常量时,将使用const关键字。 在不使用这些关键字的情况下,可以声明变量并为其分配一个特定值,但是不建议这样做。

▍关键字var


在ES2015标准之前,使用var关键字是声明变量的唯一方法。

 var a = 0 

如果在此构造中省略var ,则该值将分配给未声明的变量。 该操作的结果取决于程序运行的模式。

因此,如果启用了所谓的严格模式,则将导致错误。 如果未启用严格模式,则将发生隐式变量声明,并将其分配给全局对象。 特别是,这意味着即使在函数完成工作后,在某个函数中以这种方式隐式声明的变量也将可用。 通常,期望函数中声明的变量不会“超出”其限制。 看起来像这样:

 function notVar() { bNotVar = 1 //    } notVar() console.log(bNotVar) 

它会1控制台上得到1 ,通常没有人期望程序会出现这种行为,表达式bNotVar = 1看起来并不像尝试声明和初始化变量,而是试图访问在函数外部bNotVar = 1的变量(这是很正常的)。 结果,变量的隐式声明会使读取代码的人感到困惑,并可能导致程序异常。 稍后我们将讨论功能和范围,现在,当表达式的含义是声明变量时,请始终尝试使用专用关键字。 如果在此示例中,函数主体被重写为var bNotVar = 1 ,则尝试启动上述代码片段将导致错误消息(可以在浏览器控制台中看到)。

例如,它可能看起来像这样: Uncaught ReferenceError: bNotVar is not defined 。 其含义可以归结为以下事实:程序无法使用不存在的变量运行。 初次启动程序时,看到这样的错误消息比编写无法理解的,可能表现异常的代码要好得多。

如果在声明变量时未对其进行初始化,未为其分配任何值,则将自动为其分配undefined的值。

 var a //typeof a === 'undefined' 

通过使用var关键字声明的变量可以通过为它们分配新的值来重复声明(但这会使读取代码的人感到困惑)。

 var a = 1 var a = 2 

您可以在一个表达式中声明几个变量:

 var a = 1, b = 2 

变量的范围称为程序的范围,在该程序中可以访问(可见)此变量。

使用函数外部的var关键字初始化的变量分配给全局对象。 它具有全局范围,可从程序中的任何位置访问。 如果使用函数内部的var关键字声明了变量,则该变量仅在该函数内部可见,是该函数的局部变量。

如果在使用var的函数中声明了变量,且其名称与全局范围内某个变量的名称匹配,则它将“覆盖”全局变量。 也就是说,在函数内部访问此类变量时,它将使用其本地版本。

重要的是要理解,块(用大括号括起来的代码区域)不会创建新的可见性区域。 调用函数时会创建一个新的作用域。 var关键字具有所谓的功能范围,而不是功能块。

如果在功能代码中声明了变量,则整个功能代码都可以看到该变量。 即使在函数代码的末尾用var声明了变量,您也可以在代码的开头引用它,因为引发变量(提升)的机制在JavaScript中起作用。 该机制“提高”变量声明,但不提高其初始化操作。 这可能会引起混乱,因此将其作为在函数开始时声明变量的规则。

let关键字let


let关键字出现在ES2015中,可以简化为var的“块”版本。 使用let关键字声明的变量的范围仅限于声明了它的块,运算符或表达式以及嵌套块。

如果“ let”一词本身看起来不太清楚,则可以想象使用了“ let”一词。 然后,可以将表达式let color = 'red'转换为英语:“让颜色为红色”,并转换为俄语:“使颜色为红色”。

通过使用let关键字,您可以消除与var关键字相关联的歧义(例如,您不能使用let两次声明相同的变量)。 例如,在初始化循环时,在函数外部使用let不会创建全局变量。

例如,这样的代码将导致错误:

 for (let i = 0; i < 5; i++) {   console.log(i) } console.log(i) 

如果在初始化循环时使用计数器var声明计数器i ,则在完成循环后, i将在循环外部可用。

如今,在基于现代标准开发JS程序时,您可以完全放弃var而仅使用letconst关键字。

▍关键字const


使用varlet关键字声明的变量可以被覆盖。 如果使用const代替这些关键字,则不能为通过常量帮助声明和初始化的常量分配新值。

 const a = 'test' 

在此示例中,不能为常数a分配新值。 但应注意,如果a不是原始值(例如数字),而是对象,则使用const关键字不会保护该对象不受更改。

当他们说将对象写入变量时,实际上是指变量引用该对象。 此链接无法更改,并且链接可以指向的对象也可以更改。

const关键字不会使对象不可变。 它只是防止以相应的常量编写的对其引用的更改。 看起来是这样的:

 const obj = {} console.log(obj.a) obj.a = 1 // console.log(obj.a) //obj = 5 //  

obj常量中,初始化后会写入一个新的空对象。 尝试访问其不存在的属性a不会导致错误。 控制台变得undefined 。 之后,我们向对象添加一个新属性,然后再次尝试访问它。 这次,此属性的值1进入控制台。 如果取消注释示例的最后一行,则尝试执行此代码将导致错误。

const关键字与let非常相似,尤其是它具有块作用域。

在现代条件下,完全可以接受使用const关键字,仅在特殊情况下才允许使用,声明其值不打算更改的所有实体。 怎么了 事实是,最好努力使用最简单的可用结构,以免使程序复杂化并避免错误。

资料类型


JavaScript有时被称为“非类型化”语言,但事实并非如此。 确实可以将不同类型的值写入变量,但是JavaScript中还是有数据类型。 特别是,我们正在谈论原始和对象数据类型。

为了确定某个值的数据类型,可以使用typeof运算符。 它返回一个指示操作数类型的字符串。

▍原始数据类型


以下是原始JavaScript数据类型的列表:

  • number
  • string (字符串)
  • boolean (布尔值)
  • null (特殊null值)
  • undefined (特殊值undefined
  • symbol (在特殊情况下使用的符号,出现在ES6中)

此处,数据类型的名称以typeof运算符返回它们的形式给出。

让我们讨论一下此列表中最常用的数据类型。

类型编号


JavaScript中number类型的值表示为64位双精度浮点数。

在代码中,数字文字在十进制系统中表示为整数和小数。 您可以使用其他方法来记录数字。 例如,如果在数字文字的开头有前缀0x它被视为以十六进制表示的数字。 数字也可以用指数符号表示(在这种数字中,您可以找到字母e )。

以下是整数条目的示例:

 10 5354576767321 0xCC //   

这是分数。

 3.14 .1234 5.2e4 //5.2 * 10^4 

数值文字(此行为也是某些其他原始类型的特征),当您尝试将它们作为对象访问时,在操作期间会自动将其转换为相应的对象,这些对象称为“对象包装器”。 在这种情况下,我们正在谈论对象包装器Number

例如,此处看起来像是尝试访问变量a ,其中在谷歌浏览器控制台中将数字文字作为对象写入其中。


数字对象换行工具提示

例如,如果您使用Number类型的对象的toString()方法,它将返回数字的字符串表示形式。 看起来像可以在浏览器控制台(以及常规代码)中执行的相应命令,如下所示:

 a.toString() 

注意方法名称后面的双括号。 如果您不放置它们,则系统不会给出错误,但是,控制台将显示一些与数字5完全不同的东西,而不是预期的输出。

全局Number对象可以以构造函数的形式使用,可以在其帮助下创建新的数字(尽管这种形式几乎从未使用过),也可以将其用作独立实体,而无需创建它的实例(即,一些数字表示)帮助)。 例如,其Number.MAX_VALUE属性包含可以用JavaScript表示的最大数值。

类型字符串


string类型的值是string序列。 这些值被指定为用单引号或双引号引起来的字符串文字。

 'A string' "Another string" 

可以使用反斜杠字符将字符串值分为几部分。

 "A \ string" 

字符串可能包含所谓的转义序列,当将字符串打印到控制台时会对其进行解释。 例如,序列\n表示换行符。 反斜杠字符还可以用于将引号添加到包含在同一引号中的字符串。 用\转义引号字符会导致系统无法将其视为特殊字符。

 'I\'ma developer' 

可以使用+运算符来连接字符串。

 "A " + "string" 

模板文字


ES2015引入了所谓的模式文字或模式字符串。 它们是用反引号( ` )括起来的字符串,并具有一些有趣的属性。

 `a string` 

例如,在模板文字中,您可以替换某些值,这些值是评估JavaScript表达式的结果。

 `a string with ${something}` `a string with ${something+somethingElse}` `a string with ${obj.something()}` 

使用反引号使编写多行字符串文字变得容易:

 `a string with ${something}` 

布尔型


JavaScript有两个使用布尔值的保留字-分别为true (true)和false (false)。 比较运算(例如=====<> )返回truefalse

逻辑表达式用于ifwhile等构造中,有助于控制程序的进度。

应该注意的是,在期望为truefalse情况下,您可以使用语言自动将其视为真(真)或假(假)的其他值。

特别是,以下是错误值:

 0 -0 NaN undefined null '' //  

其余值为true。

输入空值


JavaScript具有一个特殊的null值,该值指示不存在值。 其他语言也使用类似的含义。

类型未定义


写入某个变量的undefined值表示该变量未初始化,并且没有任何值。

该值是从没有使用return关键字显式返回结果的函数中自动返回的。 如果函数接受未指定的参数,则在调用该参数时未将其设置为undefined

为了检查undefined的值,可以使用以下构造。

 typeof variable === 'undefined' 

▍物件


所有不是基本值的值都具有对象类型。 我们在谈论函数,数组,所谓的“对象”以及许多其他实体。 所有这些数据类型都是基于object类型的,尽管它们在很多方面都存在差异,但是它们有很多共同点。

表达方式


表达式是代码片段,可以根据执行的计算将特定值处理并获得。 JavaScript有几种类别的表达式。

算术表达式


计算结果为数字的表达式属于此类别。

 1 / 2 i++ i -= 2 i * 2 

字符串表达式


计算此类表达式的结果是字符串。

 'A ' + 'string' 'A ' += 'string' 

主要表达


文字,常量和对标识符的引用都属于此类。

 2 0.02 'something' true false this // ,     undefined i // i     

这还包括JavaScript的一些关键字和构造。

 function class function* // yield // /   yield* //     async function* //   await //     /pattern/i //  () // 

数组和对象初始化表达式


 [] //  {} //  [1,2,3] {a: 1, b: 2} {a: {b: 1}} 

逻辑表达式


在逻辑表达式中,使用逻辑运算符,其计算结果为逻辑值。

 a && b a || b !a 

属性访问表达式


这些表达式使您可以访问对象的属性和方法。

 object.property //   ( )  object[property] object['property'] 

对象创建表达式


 new object() new a(1) new MyRectangle('name', 2, {a: 4}) 

函数声明表达式


 function() {} function(a, b) { return a * b } (a, b) => a * b a => a * 2 () => { return 2 } 

呼叫表达


这样的表达式用于调用对象的函数或方法。

 ax(2) window.resize() 

处理对象


上面我们已经遇到对象,谈论对象文字,调用它们的方法,访问它们的属性。 在这里,我们更详细地讨论对象,尤其是考虑原型继承机制和class关键字的使用。

▍原型继承


JavaScript在现代编程语言中脱颖而出,因为它支持原型继承。 大多数面向对象的语言都使用基于类的继承模型。

每个JavaScript对象都有一个特殊的属性( __proto__ ),该属性指向其原型的另一个对象。 一个对象继承了原型的属性和方法。

假设我们有一个使用对象文字创建的对象。

 const car = {} 

或者我们使用Object构造函数创建了一个对象。

 const car = new Object() 

在上述任何一种情况下, car对象的原型都是Object.prototype

如果创建也是对象的数组,则其原型为Array.prototype对象。

 const list = [] //  const list = new Array() 

您可以如下验证。

 car.__proto__ == Object.prototype //true car.__proto__ == new Object().__proto__ //true list.__proto__ == Object.prototype //false list.__proto__ == Array.prototype //true list.__proto__ == new Array().__proto__ //true 

在这里,我们使用了__proto__属性,开发人员不必使用它,但是您通常可以访问它。 应该注意的是,获取对象原型的一种更可靠的方法是使用全局ObjectgetPrototypeOf()方法。

 Object.getPrototypeOf(new Object()) 

具有该原型的对象可以访问该原型的所有属性和方法。 例如,在这里看起来像他们的数组列表。


数组提示

所有对象的基本原型是Object.prototype

 Array.prototype.__proto__ == Object.prototype 

Object.prototype原型。

我们上面看到的是原型链的示例。

尝试访问对象的属性或方法时,如果对象本身不具有此类属性或方法,则在其原型中搜索对象,然后在原型原型中进行搜索,依此类推,直到找到所需的对象或直到原型链不会结束。

除了使用new运算符以及使用对象常量或数组常量创建对象之外,还可以使用Object.create()方法创建对象的实例。 传递给此方法的第一个参数是一个对象,它将成为使用该方法创建的对象的原型。

 const car = Object.create(Object.prototype) 

您可以使用isPrototypeOf()方法检查某个对象是否是另一个对象的原型链的一部分。

 const list = [] Array.prototype.isPrototypeOf(list) 

构造函数


上面,我们使用该语言中已经可用的构造函数创建了新对象(调用它们时,将使用new关键字)。 . .

 function Person(name) { this.name = name } Person.prototype.hello = function() { console.log(this.name) } let person = new Person('Flavio') person.hello() console.log(Person.prototype.isPrototypeOf(person)) 

-. , this . name , . . - , name , .

, name , . , , , hello() . , Person hello() ( ).


ES6 JavaScript «».

JavaScript . , JS . , , , « » . , , , , , .


.

 class Person { constructor(name) {   this.name = name } hello() {   return 'Hello, I am ' + this.name + '.' } } 

, new ClassIdentifier() .

constructor , .

. hello() — , , . Person .

 const flavio = new Person('Flavio') flavio.hello() 

,


. , , , , .

, ( ) , , -, .

 class Programmer extends Person { hello() {   return super.hello() + ' I am a programmer.' } } const flavio = new Programmer('Flavio') flavio.hello() 

hello() Hello, I am Flavio. I am a programmer .

(), .

super .


, , , , , . ( static ) , .


JavaScript , (, ) . , , .


, get set . — , , . -, — .

 class Person {   constructor(name) {     this.userName = name   }   set name(value) {     this.userName = value   }   get name() {     return this.userName   } } 

总结


, , JavaScript. .

亲爱的读者们! JS, , class.

Source: https://habr.com/ru/post/zh-CN429838/


All Articles