1+1=10

扬长避短 vs 取长补短

JavaScript学习笔记(三)

继续梳理JavaScript基本概念。

原始值(Primitive values)

这个名字取得... 。是不是叫 原始数据类型或基础数据类型 更合适一些。

JavaScript 的原始值(primitive values)是一种既不是不是对象,也没有方法或属性的数据。所有原始值都是不可变的,它们的值不能被修改。

JavaScript 有7中原始数据类型:

  • string
  • number
  • boolean
  • undefined
  • symbol
  • null

这些类型,我们可以用typeof查看:

console.log(typeof null) // object
console.log(typeof undefined) // undefined
console.log(typeof true) // boolean
console.log(typeof 1) // number
console.log(typeof '123') // string
console.log(typeof 1111n) // bigint
console.log(typeof Symbol()) // symbol

注意:

  • null 返回的类型是 object,这是历史原因造成的。以后估计也不会改了。要测试null,不能使用typeof,需要用===null来测试。
  • Symbol没有字面量写法,也不能用new创建。
  • bigint后缀是n

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"

包装器

这些原始数据类型没有成员方法,但是表现得却和有方法一样。比如:

let name = "Debao"
console.log(name.toUpperCase()) // DEBAO
console.log(name.startsWith("De")) // true

这是因为:Javascript自动将值装入包装对象中,并访问该对象的属性。

除了null和undefined外,所有的原始类型都有对象的对象包装类型:

类型 包装器 备注
null 不适用 只有一个值 null
undefined 不适用 只有一个值 undefined
boolean Boolean 两个值 true 与 false
number Numer 包括 Infinity、-Infinity、NaN、0、-0 等
string String
bigint BitInt
symbol Symbol

包装器属于对象类型:

let v1 = 100
let v2 = new Number(100)

console.log(typeof v1) // number
console.log(typeof v2) // object
console.log(v1 == v2) // true
console.log(v1 === v2) // false

QJSEngine

QJSEngine的QJSPrimitiveValue中不包括 Symbol和BigInt,另一方面把Number分成了Integer和Double:

  • QJSPrimitiveValue::Undefined
  • QJSPrimitiveValue::Null
  • QJSPrimitiveValue::Boolean
  • QJSPrimitiveValue::Integer
  • QJSPrimitiveValue::Double
  • QJSPrimitiveValue::String

typeof

对原生类型

类型 typeof 结果 备注
null "object" 历史原因
undefined "undefined"
boolean "boolean"
number "number"
string "string"
bigint "bigint"
symbol "symbol"

对其他类型(所有使用new调用的构造函数,都会返回下面的非基本类型):

类型 typeof 结果 备注
function/class "function" class也是函数
其他对象 "object"

代码

console.log(typeof function () {} === "function") // true
console.log(typeof class C {} === "function") // true
console.log(typeof Math.sin === "function") // true
console.log(typeof function* () {} === "function") // true
console.log(typeof async function () {} === "function") // true
console.log(typeof async function* () {} === "function") // true

// pay attention to this one
console.log(typeof new Function() === "function") // true

注:

  • 原生类型不可变。
  • object和function可变。只是function也是object,只不过它多了可调用的技能!33

对象 (Objects),引用类型

在Javascript中,对象是唯一的可变的值类型,函数是其特例。函数是可执行的对象,它有自己的属性和方法,可以作为参数传递给其他函数,也可以作为其他函数的返回值,还可以创建闭包。

对象在JavaScript中是引用类型。

let p1 = {name : '1+1=10'}
let p2 = p1
p2.name = '1+1=2'

console.log(p1.name) // 1+1=2

JavaScript中的数组(array)、日期(date)、正则表达式(regexp)等都是对象。

对象 vs 对象

感觉有点混乱:

  • new创建的所有东西都是对象。
  • 使用{}这种键值对创建的东西是对象。

为了区分,可以:

  • {}键值对这种叫做 普通对象
  • []这种array叫做 数组对象
  • ...

QJSEngine

对于引用类型,QJSEngine提供了 QJSManagedValue类,如下是其支持的对象类型:

  • QJSManagedValue::Undefined
  • QJSManagedValue::Boolean
  • QJSManagedValue::Number
  • QJSManagedValue::String
  • QJSManagedValue::Object
  • QJSManagedValue::Symbol
  • QJSManagedValue::Function

引用类型不能跨多个QJSEngine使用。

字面量

字面量和 基础类型(原始值)还是引用类型(对象)没必然关系:

  • 数字字面量,如 1.23420x7f
  • 字符串字面量,如 "hello"'world'"你好"
  • 布尔字面量,truefalse
  • 空字面量,null
  • 未定义字面量,undefined
  • 对象字面量,用花括号 {} 包围一组键值对,如 {name: "Alice", age: 18}
  • 数组字面量,用方括号 [] 包围一组元素,如 [1, 2, 3]
  • 函数字面量,用 function 关键字定义一个函数,如 function(x) {return x * x;}
  • 正则表达式字面量,用斜杠 / 包围一个模式,如 /[a-z]+/
  • 模板字面量,用反引号 ` 包围一段文本,可以嵌入表达式,如 Hello, $ {name}!

小结

  • 区分 基础类型(7种原始值)和 引用类型(对象 和 函数)
  • 除null和undefined外,其他原始值都有对应的对象类型(使用new创建)
  • 由于历史原因,null的typeof值是 'object'
  • 对象和基于键值对{}创建的普通对象
  • 字面量可用于基础类型和引用类型

参考

Comments