基本类型包装

2019-07-10  本文已影响0人  了凡和纤风

为了便于操作基本类型值,ECMAScript还提供了三个特殊的引用类型:Boolean、Number、String。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。

const s1 = 'some text'
const s2 = s1.substring(2)

// 其实,为了让我们实现这种直观的操作,后台已经自动完成了一些列的处理
/*
  1. 创建String类型的一个实例
  let s1 = new String('some text')
  2. 在实例上调用指定的方法
  let s2 = s1.substring(2)
  3. 销毁这个实例
  s1 = null
*/

经过此番处理,基本的字符串就变得和对象一样了。而且,上面着三个步骤也分别适用与Boolean和Number类型对应的布尔值和数字值
引用类型与基本类型的主要区别就是对象的生存期。基本包装类型的生命只存在于一行代码的执行瞬间,然后就会被销毁。这就意味着我们不能在运行时为基本类型值添加属性和方法。

let s1 = 'some text'
s1.color = 'cyan'
console.log(s1.color) // undefined

Object 构造函数也会项工厂方法一样,根据传入值的类型返回相应基本包装类型的实例。

const obj = new Object('some text')
console.log(obj instanceof String) // true

需要注意的是,适用 new 基本调用包装类型的构造函数, 与直接调用同名的转型函数是不一样的。

let value = '25'
let number = Number(value) // 转型函数
console.log(typeof number) // 'number'

let obj = new Number(value) // 构造函数
console.log(typeof obj) // 'Object'
Boolean 类型

Boolean 类型是布尔值对应的引用类型。要创建Boolean对象,适用构造函数或者在布尔表达式中使用Boolean对象。

let falseObject = new Boolean(false)
console.log(falseObject && true) // true

let falseValue = false
console.log(falseValue && true) // false

如上,在布尔表达式中所有对象都会被转换为true,因此falseObject对象在布尔表达式中代表的是 true。结果, true && true = true
此外,他们之间还有两个区别

// 通过构造函数创建的实例,typeof是object,instanceof指向构造函数
console.log(typeof falseObject) // object
console.log(typeof falseValue) // boolean

console.log(falseObject instanceof Boolean) // true
console.log(falseValue instanceof Boolean) // false
Number类型

Number是与数字对应的引用类型,要创建Number对象,可以在调用Number构造函数时向其中传递相应的数值。

let numberObject = new Number(10)

与Boolean类型一样。,Number类型也重写了valueOf() 、toLocaleString() 和 toString() 方法。重写后的 valueOf() 返回对象表示的基本类型的数值。另外两个方法返回字符串形式的数值。此外,可以为toString() 方法传递一个表示基数的参数,告诉它返回几进制的数值

let num = 10
console.log(num.valueOf()) // 10
console.log(num.toString(2)) // '1010'
console.log(num.toString(8)) // '12'
console.log(num.toString(10)) // '10'
console.log(num.toString(16)) // 'a'
let num1 = 10
let num2 = 10.004
let num3 = 10.005

console.log(num1.toFixed(2)) // '10.00'
console.log(num2.toFixed(2)) // '10.00'
console.log(num3.toFixed(2)) // '10.01'

// 能够自动舍入的特性,使得 toFixed()方法很适合处理货币值。
// 但是需要注意的时,不同浏览器给这个方法设定的舍入规则可能不同。

另外可用于格式化数值的方法还有 toExponential(),改方法返回指数表示法(也称e表示法)。此外还有toPrecision()
与Boolean对象类似,Number对象也以后台方式为数值提供了重要的功能。但与此同时,我们仍然不建议直接实例化Number类型,原因与显式创建Boolean 对象一样

let numberObject = new Number(10)
let numberValue = 10
console.log(typeof numberObject ) // object
console.log(typeof numberValue ) // number
console.log(numberObject  instanceof Number) // true
console.log(numberValue instanceof Number) // false
String类型

String类型是字符串的对象包装类型,可以使用下面这样使用String构造函数来创建

let stringObjject = new String('hello world')

String对象的方法也可以在所有基本的字符串中访问到。其中,继承的valueOf() 和 toLocaleString() 和 toString()方法,都返回对象所表示的字符串值。String类型的每个实例都包含length属性,表示字符串包含多少字符,即使字符串中包含多节字符(不是占一个字节的ASCII字符),每个字符也仍然算一个字符。

let str1 = 'Hello World'
let str2 = '你好!'
console.log(str1.length) // 11
console.log(str2.length) // 3

字符串方法

Global 对象

Global(全局)对象可以说是ECMAScript中最特别的一个对象了。可以说,不属于任何其他对象的属性和方法,最终都是它的属性和方法;所有在全局作用域中定义的属性和函数,都是Global对象的属性。诸如isNaN()、parseInt()...,除此之外,Global对象还包含其他一些方法。

URI编码方法 encodeURI()、encodeURIComponent()

Global 对象的 encodeURI() 和 encodeURIComponent()方法可以对URI(Uniform Resource Identifiers,通用资源标识符)进行编码,一边发送给浏览器。它们可以使用特殊的UTF-8编码替换所有无效的字符(比如空格),从而让浏览器能够接受理解。

const uri = 'http://www.wrox.com/illegal value.htm#start'
// http://www.wrox.com/illegal%20value.htm#start
console.log(encodeURI(uri))
//http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start
console.log(encodeURIComponent(uri))

两者的区别在于,encodeURI() 不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、? 和 #;而encodeURIComponent() 则会对它发现的任何非标准字符进行编码。
解码 decodeURI() 、decodeURIComponent()
与上面两个方法对应的分别是,decodeURI() 和 decodeURIComponent()。其中decodeURI()只能对使用encodeURI()的字符进行解码。因为encodeURI()无法替换 # ? 等,所有对应的encodeURI也无法解析。如下:

const uri = 'http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start'
 // http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start
console.log(decodeURI(uri))
 // http://www.wrox.com/illegal value.htm#start
console.log(decodeURIComponent(uri))

eval() 大概是ECMAScript语言中最强大的一个方法了。eval()方法就相当于是一个完整的ECMAScript解析器,它只接受一个参数,即要执行的ECMAScript字符串

eval('alert("Hello World")')
// 等价于
alert("Hello World")

eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此在被执行的代码具有与该环境相同的作用域链。这意味着通过eval()执行的代码可以引用在包含环境中定义的变量。

const msg = "today"
eval('console.log(msg)')

// 定义函数
eval(`
  function sayHi() {
    console.log('Hello World')
  }
`)
// 调用函数
sayHi()

在eval()中创建的任何变量或函数都不会被提升。在严格模式下,外部访问不到eval()中创建的任何变量或函数,为eval() 赋值也会导致错误

'use strict'
eval = 'hi' // causes errpr
window对象

ECMAScript 虽然没有指出如何直接访问 Global 对象,但Web浏览器都是将这个全局对象作为window对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就成为了window对象的属性

var color = 'red'
function getColor() {
  console.log(window.color)
}
window.getColor()

这里需要注意的是let、const声明的变量不会挂载在 window下
刚才查阅的过程中发现了一道有意思的面试题

let len = 10;
function fn() {
  console.info(this.len)
}
fn(); // this执行window。 undefined
let Person = {
  len: 5,
  say: function() {
    // 再次调用fn,this依然是window。
    fn(); undefined

    // 这里将 fn作为参数传入,变成了arguments的属性
    // 但是arguments没有定义len这个属性,所有依然是 undefined
    arguments[0](); // undefined
    }
}
Person.say(fn);
Math对象

ECMAScript还未保存数学公式和信息提供了一个公共位置,即Math对象。与在JavaScript中直接编写的计算功能相比,Math对象提供的计算功能执行起来要快得多。Math对象中还提供了辅助完成这些计算数学和方法

Math对象的属性
Math对象包含的属性大都是数学计算中可能会用到的一些特殊值。

min() 和 max() 方法
用于返回一组数中的最大值和最小值

let max = Math.max(3, 12, 9) // 12
let min = Math.min(2, 3,  5) // 2

// 找到数组中的最大(最小)值,可以这样使用
let arr = [1, 3, 5, 7, 9]
let arrMax = Math.max.apply(Math, arr)
console.log(arrMax ) // 9

舍入方法

random() 方法
方法返回大于等于0小于1的一个随机数。套用下面的公式,就可以利用Math.random()从某个范围内随机选择一个值。
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能值)

let num = Math.floor(Math.random() * 10 + 1) // 1-10之间的整数

let num2 = Math.floor(Math.random() * 200 - 100) // -100 - 100

Math对象中还包含其他一些与完成各种简单或复杂计算有关的方法。其他方法

小结:

在所有代码执行之前,作用域中就已经存在两个内置对象:Global 和 Math。在大多数ECMAScript实现中都不能直接访问Global对象;不过,Web浏览器实现了承担该角色的window对象。全局变量和函数都是Global对象的属性。Math对象提供了很多属性和方法,用于辅助完成复杂的数学计算任务。

上一篇 下一篇

猜你喜欢

热点阅读