阿里面试,js对象包装类|new关键字
试题引入
// 阿里面试题
var str = 'abc'
str += 1
var test = typeof (str)
if (test.length == 6) {
test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);
会输出一个什么呢? 这个问题就涉及到了js对象包装类的概念。
JavaScript对象
在 JavaScript 中,对象是一种无序的数据集合,它由键值对组成。对象可以用来存储和操作各种类型的数据。大家都知道,除了基本数据类型其他都是对象
var mrXu = {
name: 'Mr.Xu',
age: 20,
sex: 'male',
say: function () {
console.log('hello, my name is ' + this.name);
},
drink: function () {
console.log('I drink coffee');
},
}
这就是一个对象,由属性和方法构成,可以存储各种类型的数据。
对象中用点的方式与用中括号访问的区别
那么大家都知道,我们可以用点的方式去访问对象中的某个属性,如果这个属性不存在,那他就会自动为我们创建一个属性
mrXu.grilFriend = 'lilei'
console.log(mrXu);
如果我们不是用点的方式去访问,如果我们用中括号的方式去访问呢?
即:mrXu['grilFriend']=xxx,其实答案也是一样的,如果对象中不存在grilFriend这个属性,他也会帮我们添加这个属性。
那既如此,中括号和点的方式有什么区别呢?
如果我们写了var abc = 'girlFirend',但是我们想把这个abc的值拿去当对象的属性去添加时,mrXU.abc = '张若琳',我们这么写它会默认把abc当成一个属性去添加或者访问,想要取到abc中的值作为属性加到对象中可以用 mrXu[abc] = '张若琳',如果不想要abc的值作为属性而是只要abc作为属性可以加个引号 mrXu['abc'] = '张若琳'
new关键字
我们创建对象时可以通过new的方式去创建,例如var obj1 = new Object(),那么在这里这个new到底是什么,他做了一件什么事情呢?
在我们手动去写一个类的时候我们是不是这样写的。
function Person(color) {
this.name = '张三',
this.age = 18
this.color = color
}
然后我们再通过 var p1 = new Person(),当然这里提一嘴,我们会约定俗成的把这个对象类首字母大写
,接下来思考为什么我们只是写了一个普通的Person函数,通过new就能够构建一个对象出来呢?
- 毫无疑问,他是不是至少返回了一个对象?如果他不做一个return操作,那我们调用Person()它没有返回值,那输出这个p1结果不就是undefined吗?
- 想到这里,相信大家已经明白这个new做了什么事情了,我们已经说过通过对象点的方式可以给一个对象没有的属性添加上这个属性,那么这个new事实上也就是创建了一个obj空对象,Person.call(obj)将this指向obj,然后绑定obj.
__protp__
= this.constructor.prototype,然后通过我们写的this.去添加属性并赋值,最后再把这个obj给返回,即:
function Person(color) {
obj = {
}
Person.call(obj)
obj.__protp__ = this.constructor.prototype
this.name = '张三'
this.age = 18
this.color = color
return obj
}
既然如此,那我们是不是可以自己写一个关键字,然后通过自己的关键字去创建对象?
console.log('---------------------------------------');
function NewPerson(color) {
var that = {
}
NewPerson.call(that)
that.__protp__ = that.constructor.prototype
that.name = '张三'
that.age = 18
that.color = color
return that;
}
let obj4 = NewPerson('black')
console.log(obj4)
console.log('------------------------------------------');
包装类
var num = new Number(123)
num.abc = 'abc'
console.log(num);
我们都知道,通过new一个Number()我们便创建了一个Number类型的对象,那么对这个对象进行添加abc属性合情合理,输出num也自然会是一个对象的形式并且存在abc属性,值为abc
但是我们如果是这样呢?
var num1 = 123
num1.abc = 'hello'
console.log(num1.abc); // undefined
大家都知道这是一个基本数据类型,既然不是对象,那就不能通过点的方式去添加或者访问属性,那么我们输出这个num1.abc讲道理是不是应该报错?如果不报错岂不是伤天害理了?但是最后他来了一个undefined。这是为什么呢? 这就涉及到了包装类,这是一个隐式转换的过程
- 首先在JavaScript引擎中,我们只是声明了一个基本数据类型并且赋值,但是在引擎的眼里它是这么操作的:var num1 = new Number(123),既然是这么干的那这不就是一个对象吗?添加属性合情合理,但是引擎也没那么傻,他会发现你只是一个基本数据类型,在你添加一个属性之后,他立马会执行一个delete操作,删除对象中你添加的这个属性,因此你通过点的方式去访问,他并不会报错,而是由于你访问了一个不存在的属性最后输出结果undefined。
var str = 'abc'
console.log(str * 2); // NaN
console.log(str.length); // 3 这里的length是本身就内定了的,我们在访问这个属性的时候引擎不会去删除
str.length = 2
console.log(str.length); // 3 为什么不是2?
再来看一份代码,到这里大家应该都知道了,引擎会自动new String('abc'),因此他也被当成一个对象来使用,但是这里的length是一个内置属性,返回这个字符串的长度,这个是底层已经写好了的,那我们能不能修改呢?
- 我们通过str.length = 2的方式改成2,最后输出还是输出了abc的长度3,还是因为包装类的过程,你添加的这个length和字符串自带的length属性是两码事,他们毫无关联,在你添加length属性之后,引擎立马反应过来这是一个基本数据类型,没有当成对象的必要,因此马上delete操作,删除掉这个属性,最后你输出他的length也是字符串自带的length,因此还是3.
了解了上述概念之后我们回到阿里面试题
// 阿里面试题
var str = 'abc'
str += 1
var test = typeof (str)
if (test.length == 6) {
test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);
分析过程:
- 首先引擎new String('abc')
- 然后你做了一个加一操作,但是由于这是一个字符串,他无法做四则运算,最后会返回一个NaN
- 然后你去判断了一下str的类型,毫无疑问,这是一个字符串类型因此讲String赋值给test
- 既然是字符串,就有内置的length属性,值为字符串的长度,长度为6
- 然后通过判断发现长度确实是6,你又对它进行了一个属性添加操作,然后引擎发现这只是一个基本数据类型,于是立马做了delete操作,删除掉你添加的这个属性
- 最后你想访问你添加的这个属性,但是已经被删除了,因此最终会输出一个undefined。
结语
在 JavaScript 中,包装类如String
、Number
、Boolean
等,为基本数据类型提供了更丰富的操作和方法。它们使得基本数据类型能够像对象一样被处理,增强了语言的表达能力。理解包装类的特性和用法,有助于我们更灵活地进行编程,更好地处理数据类型的转换和操作,提升代码的质量和效率。
转载自:https://juejin.cn/post/7365833245957570595