likes
comments
collection
share

JavaScript 中的对象和包装类:面试解析与阿里面试题分析

作者站长头像
站长
· 阅读数 29

前言

在JavaScript中有句话:万物皆对象。其实本质上在JS这门编程语言当中,任何东西都可以称之为是一个对象。对象在js中起着举足轻重的作用。我们通过面试题解析了解对象和包装类。

正文

面试题

var arr = [12345]
arr.length = 2
console.log(arr)

var str = 'abcde'
str.length = 2
console.log(str)

分别会输出什么呢?

分别输出[1,2]abcde

为什么会输出这些那?我们先对对象和包装类进行了解。当我们理解后挑战阿里面试题。

什么是对象

在JavaScript中,除了数字、字符串、数字、undefined和null这五种原始数据类型,其余的都是对象。数字、字符串和布尔值虽然具有一些类似对象的行为,比如有一些方法可以调用,但它们并不是真正意义上的对象。

对象是属性的集合:由一系列的键值对组成,键表示属性名,值表示属性所对应的数据。

对象具有特定行为:可以包含方法(函数)来定义对象的操作。

对象可以可动态修改:可以在对象创建后添加、修改或删除属性。

对象的创建

对象的创建有三种方法:

  1. 创建对象字面量。

    直接使用花括号创建。eg:

    var object = {}
    

    优点:代码量少,简便。

  2. 调用系统自带的构造函数 new Object()。

    eg:

    var object = new Object()
    
  3. 调用自定义的构造函数。

    eg:

    function People(name, age, sex) {
        this.name = name
        this.age = age
        this.sex = sex
    }
    
    let p1 = new People('小李', 18, 'boy')
    

    优点:可以批量创建对象。

new关键字

构造函数就是一种特殊的函数,只有在new关键字调用后才会创建一个新的对象,并将这个对象与构造函数关联起来。

function People(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
}

let p1 = new People('小李', 18, 'boy')

构造函数被new调用的过程:

  1. new会在构造函数中创建一个object对象。
  2. 通过call方法将this指向object对象
  3. 将object对象的原型指向构造函数的原型。
  4. 执行函数中的逻辑代码(相当于往object对象上添加属性)。
  5. 返回object对象。
function People(name, age, sex) {
    //new会在构造函数中创建一个this对象
    // var object = {}
    
    //通过call方法将this指向object对象
    //People.call(object)
    
   //将object对象的原型指向构造函数的原型
   //object.__proto__ === People.prototype

    //执行函数中的逻辑代码(相当于往object对象上添加属性)
    this.name = name
    this.age = age
    this.sex = sex

    //返回object对象
    // return object
}

let p1 = new People('a', 18, 'boy')

对象的增删改查

var xm = {
    name: '李明',
    age: 18,
    sex: 'boy',
    run: function () {
        console.log('I am running')
    },
    drink: function () {
        console.log('I am drinking,cool!')
    },
    health: 100
}

对该对象进行增删改查操作。

  • 增加对象的属性。

    有两种方法:

    1. 方法一:使用点号。

      xm.girlFriend = '小美'
      //添加 girlFriend:'小美' 键值对
      -----------------------------------------
      var a = 'girlFriend'
      xm.a = '小美'
      //添加 a:'小美' 键值对
      

      xm.girlFriend = '小美'中的girlFriend默认是字符,不是变量。

    2. 方法二:使用方括号。

      var a = 'girlFriend'
      xm[a] = '小美'
      //添加 girlFriend:'小美' 键值对
      ------------------------------------------
      var a = 'girlFriend'
      xm['a'] = '小美'
      //添加 a:'小美' 键值对
      

      xm[a] = '小美'中的a默认是变量,加上引号变成字符。

      该方法的优点:可以通过变量添加对象属性。

  • 删除对象的属性。

    delete xm.age
    
  • 修改对象的属性。

    xm.age = 30
    
  • 查对象的属性。

    xm.run()
    ----------------------------------------------
    console.log(xm.age)
    

    小tips:如果访问对象上不存在的属性,得到的结果是undefined,并不会报错。

包装类

包装类是JavaScript中为原始数据类型(如数字、字符串、布尔值)提供对象形式的类。常见的包装类有Number(用于数字类型)、String(用于字符串类型)和Boolean(用于布尔值类型)。包装类可以让原始数据类型具有一些类似对象的方法和属性。

当我们在基本数据类型上调用对象方法时,JavaScript会根据需要隐式地创建相应的包装对象,然后在该对象上调用方法。这种转换是临时的,调用完成后,这些临时创建是包装对象会被立即销毁。

eg1

var str = '1234'
console.log(str.length)//输出:4

为什么会输出4呢?明明说过原始数据类型是不能拥有属性和方法,怎么string类型会有length属性呢?

因为str是一个对象。

var str = '1234'
//在v8的执行过程中是这样的:str = new String ('1234')

在执行过程中,JavaScript引擎把str执行为对象,而不是原始数据类型。

eg2

var num = 987
num.str = 'hello'

console.log(num.str)

结果会是什么呢?

结果为undefined,并没有报错。因为原始数据类型是不能拥有属性和方法的,属性和方法是对象独有的。

在JavaScript引擎执行过程中,这段代码是这样的:

new Number(987).str = 'hello'
//当我们创建一个num数字类型时,JavaScript引擎会创建一个对象;并且添加str:'hello'键值对。
delete new Number(987).str
//JavaScript会发现我们想创建的是一个原始数据类型,所以会删除str属性。
console.log(num.str)//输出:undefined
//访问对象上不存在的属性,得到的结果是undefined

还记得上面的小tips吗,如果访问对象上不存在的属性,得到的结果是undefined,并不会报错。

这个隐式的过程就是包装类

eg3

var num = new Number(123)
num.abc = 'hello'
console.log(num.abc)//输出:hello
console.log(num*2)//输出:246

console.log(num.abc)输出hello,我们可以理解,因为num是通过构造函数创建的实例对象,使用可以添加对象属性。

但是console.log(num*2)输出:246,难以理解。

JavaScript 中的对象和包装类:面试解析与阿里面试题分析

对象乘以数字应为NaN,为什么这里却是246呢?

因为当num(Number构造函数创建的实例对象)参加四则运算时,JavaScript引擎会把num当作原始数据类型执行。

解答面试题

var arr = [12345]
arr.length = 2
console.log(arr)

var str = 'abcde'
str.length = 2
console.log(str)

解析:

arr是数组,也就是对象。所以可以通过arr.length = 2修改数组的长度。

str.length = 2被当作为包装类的执行过程,会被移除。

var str = 'abcde'
str.length = 2
//这两行代码在v8执行过程中被执行为:new String('abcde').length = 2

//但是v8意识到我们想创建的是字符串字面量,并不是对象。所以便删除了length属性
//delete new String('abcde').length 

console.log(str)

JavaScript引擎执行的代码为:

new String('abcde').length = 2
delete new String('abcde').length 
console.log(str)

实战阿里面试题

var str = 'abc'
str += 1
var test = typeof(str)
if (test.length == 6) {
  test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);

结果为undefined

解析:

  1. 首先,定义了一个字符串变量 str并赋值为 'abc'。
  2. 然后,执行了 str += 1,这里会进行隐式类型转换,将数字 1加到字符串 'abc'上,得到结果 'abc1'。
  3. 接着,使用 typeof 操作符获取 str 的类型,得到结果是字符串 "string"。
  4. 在 if 条件判断中,检查 typeof 的结果字符串的长度是否为 6(即 "string" 的长度),条件成立。
  5. 然而,当尝试给typeof 的返回结果(字符串)添加属性 sign 时,V8会为test添加sign属性,但是在v8意识到tset为原始数据类型后,便删除了sign属性。
  6. 如果访问对象上不存在的属性,得到的结果是undefined。
转载自:https://juejin.cn/post/7366082235243921445
评论
请登录