美文网首页
基本类型包装

基本类型包装

作者: 了凡和纤风 | 来源:发表于2019-07-10 17:06 被阅读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'
    
    • toFixed()
      这是Number类型中,很实用的一个方法。他按照指定的小数位返回数值的字符串
    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
    

    字符串方法

    • 字符方法
      • charAt() - 接收数值参数,返回字符串中对应位置的字符
      • charCodeAt() - 接收数值参数,返回字符串中对应位置字符的编码
    • 字符串操作方法
      • concat() - 接收一个或多个字符串,将他们拼接起来,与数组concat类似
      • slice() / subString() - 接受一或两个参数,返回被操纵后的字符串子串(包含指定开始,不包含结束)。
    • 字符串位置方法
      • indexOf() - 从当前字符串搜索给定的子字符串,然后返回子字符串的位置(没有则返回 -1)。
      • lastIndexOf() - 与上面类型,唯一区别是从字符串的末尾开开始查找。
    • trim() - 删除当前字符串 两边的空格。创建返回字符串副本
    • 字符串大小写转换方法
      • toLowerCase() - 转小写
      • toLocaleLowerCase() - 转小写(对特定地区少数语言需要使用这个)
      • toUpperCase() - 转大写
      • toLocaleUpperCase() - 转大写 (对特定地区少数语言需要使用这个)
    • 字符串的模式匹配方法
      • match() - 接受一个正则表达式,或一个RegExp对象。与RegExp的exec()方法类似。
      • search() - 接受正则或字符串,返回匹配到的索引,无匹配则返回-1
      • replace() - 接受两个参数,第一个参数与search()一样,第二个参数为匹配后需要替换的字符串(或一个函数)。
        • 如果是字符串,那么可以使用一些特殊的字符序列($$、$&...)
        • 如果是函数
          • 在只有一个匹配项的情况下接受三个参数:模式的匹配项、匹配项在字符串中的位置、原始字符串
          • 在定义多个捕获组的情况下,接收:模式的匹配项、第一个捕获组的匹配项、第二个...、最后两个参数仍然分别是模式匹配项在字符串中的位置、原始字符串。
      • split() - 接收一个指定的分隔符,将一个字符串分割成多个子字符串,并将结果存放在数组中(支持正则.低版本浏览器有差异)。
    • localeCompare() - 比较两个字符串
      • 如果字符串在字母表中应该排在字符串参数之前,则返回一个负数(大多情况下是 -1, 具体的值要视实现而定)
      • 如果字符串等于字符串参数,返回0
      • 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是1,具体的值同样要视实现而定)。
    • fromCharCode()
      • String的静态方法,与实例的charCodeAt相反,接收多个字符编码,返回一个对应的字符串。
    • HTML方法
      • 比如:link(url) - <a href=url>String</a>
      • 避免使用,一是因为他们大多被废弃。其二即是他们创建的标记通常无法表达语义。
    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() 方法

    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对象包含的属性大都是数学计算中可能会用到的一些特殊值。

    • Math.E - 自然对数的底数,即常量e的值
    • Math.LN10 - 10的自然对数
    • Math.LN2 - 2的自然对数
    • Math.LOG2E - 以2为底e的对数
    • Math.LOG10E - 以10为底e的对数
    • Math.PI - π的值
    • Math.SQRT1_2 - 1/2的平方根(即2的平方根的倒数)
    • Math.SQRT2 - 2的平方根

    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
    

    舍入方法

    • Math.ceil():向上取整
    • Math.floor():向下取整
    • Math.round():四舍五入取整

    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对象中还包含其他一些与完成各种简单或复杂计算有关的方法。其他方法

    小结:

    • 引用类型与传统面向对象程序设计中的类相似,但实现不同。
    • Object是一个基础类型,其他所有类型都从Object继承了基本的行为。
    • Array 类型是一组值的有序列表,同时还提供操作转换这些值的功能。
    • RegExp类型是ECMAScript支持正则表达式的一个接口,提供了最基本的和一些高级的正则表达式功能。
    • 函数实际上是Function类型的实例,因此函数也是对象。
    • 每个包装类型都映射到同名的基本类型
    • 在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据的操作。
    • 操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象

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

    相关文章

      网友评论

          本文标题:基本类型包装

          本文链接:https://www.haomeiwen.com/subject/dlrckctx.html