"为什么我给对象加的属性不见了?""new 构造函数为什么不用 return 也能拿到对象?""对象遍历为什么会拿到原型上的属性?"
重点:JS 万物皆对象
一、JS 对象是什么
简而言之,对象是用花括号 { } 包裹的键值对,
js
const a = 1
const person = {
name: '小明',
age: 18
}
二、JS 对象的创建方式
1.通过字面量创建
例如:
js
const person = {
}
这里的花括号相当于告诉了 V8 引擎,我现在写的东西是个对象,接下来的逻辑请按对象处理
2.通过 new 创建(调用官方提供的构造函数)
例如:
js
const a = new Object()
// a = {}
官方为 JS 提供了引用类型以及原始类型的构造函数,调用即可创建该类型的实例对象
3.通过自己写的构造函数通过 new 关键字调用
例如:
js
function Car(color) {
this.name = 'su7'
this.height = '1400'
this.lang = '4800'
this.weight = '1500'
this.color = color
}
const car1 = new Car('purple')
const car2 = Car('purple')
console.log(car1, car2); // Car { name: 'su7', height: '1400', lang: '4800', weight: '1500', color: 'purple' } undefined
可以看到,car1 是通过 new 生成的,car2 则是直接通过直接调用我们写的 Car 函数生成的,为什么 car1 有值,car2 却是 undefined 呢?
先看 car2 ,因为我们在函数内并没有返回值,是 undefined 情有可原 再看 car1 ,同样没有返回值,可是有值,这唯一的区别就是 car1 是通过 new 生成的, 而在 new 一个函数(此处为Car ) ,将 Car 用成了一个构造函数的样子,返回了一个实例对象,new 完源码其实是添加了返回值的,再来粗浅表达一下 new 源码大概干了些什么(不涉及原型链的部分的写法)
js
function Car(color) {
this.name = 'su7'
this.height = '1400'
this.lang = '4800'
this.weight = '1500'
this.color = color
}
const car1 = new Car('purple')
// function Car(color) {
// const a = {}
// a.name = 'su7'
// a.height = '1400'
// a.lang = '4800'
// a.weight = '1500'
// a.color = color
// return a
// }
像是官方提供的数据类型构造函数,其实是涉及原型链和原型的继承的,这个点后面文章再介绍,此文仅谈论对象的表层内容
4.Object.create()
这是官方提供的 Object 里的方法,侧重于原型的继承,后续文章详细介绍,此文提一嘴
三、对象的一些基本操作
1.对象身上的键值对是可以添加函数的,我们一般称之为方法
js
const a = {
skill: function() {
console.log('会飞');
}
}
a.skill() // 会飞
2.对象身上的增加和函数属性值
js
const a = {
skill: function() {
console.log('会飞');
}
}
a.skill() // 会飞
a.options = {
color: 'red',
size: '1000'
}
console.log(a.options); // { color: 'red', size: '1000' }
delete a.options
console.log(a.options); // undefined
此处介绍了 JS 中对象怎么删除和添加属性
四、包装类
这个名词也就是看着专业
在你定义一个字面量,不管是谁的字面量,官方都是通过 new 字段调用对应数据类型的构造函数生成的
这也是 JS 万物皆对象的依据
js
var num = 123 // new Number(123)
num.a = 'aaa'
console.log(num.a); // undefined
// // 原始类型一定无法添加属性和方法,属性和方法是对象独有的
// var num = 123 // new Number(123)
// num.a = 'aaa'
// delete num.a
// console.log(num.a); // undefined
按理来说,在给身为String 类型的 num 添加 a 属性的时候就应该报错,但是 JS 是弱类型语言,一个变量只有在被使用的时候才知道是什么类型
在打印 num.a 的时候, V8 才想起来了, num 是 String 类型,而不是一个对象,所以源码在编译运行的时候, 偷偷把 num 身上的属性值给删掉了,当值被判定 为原始类型时就会自动将包装对象上添加的属性移除
但是在给 num 加属性的时候,JS 是真让把 num 当对象使
这里再举一个例子,涉及一点原型,后端文章会具体讲
js
var str = 'hello'
typeof('hello') // string
var str = new String('hello')
str.length = 2
console.log(str.length); // 5
delete str.length
console.log(str.length); // 5
其实 JS 中,String 类型的数据身上本就有 length 属性,我这里给他再挂一个 length ,可以看到,打印出来的 str.length 还是 5 ,就算把这个 length 删了,他还是有
这个是什么原因,最主要的,就是因为 length 不是挂在 str 的表层上,他是挂在 String 的原型上,这里 str 的 length 其实是继承过来的,关于原型的介绍,后续文章会提及