你觉得var num = 123; num.abc = 'abc'; console.log(num.abc);打印的结果是什么呢
对象知多少
前言
针对上述问题,想必有不少小伙伴会发出疑问:这难道不会报错嘛?接下来,小编将从基础知识开始深入讲解其V8执行过程。
先了解对象
什么是对象
JavaScript的原始类型包括数字、字符串、布尔值、null和underfined,除了他们之外的所有值都是对象。数字、字符串和布尔值“貌似”对象,因为它们拥有方法,但它们是不可变的。
一、访问对象的属性和方法
在 JavaScript 中,访问对象的属性和方法有两种主要的语法:点语法和方括号语法。
1. 点语法
点语法是最常用的方式,通过对象名后面的点 .
加上属性名或方法名来访问。例如:
const person = {
name: 'Alice',
age: 25,
greet: function() {
console.log('Hello!');
}
};
// 访问属性
console.log(person.name); // 输出:Alice
console.log(person.age); // 输出:25
// 调用方法
person.greet(); // 输出:Hello!
2. 方括号语法
方括号语法通过对象名后面的方括号 []
包含属性名的字符串来访问。例如:
const person = {
name: 'Alice',
age: 25
};
// 访问属性
console.log(person['name']); // 输出:Alice
console.log(person['age']); // 输出:25
方括号语法在属性名包含特殊字符或是变量时特别有用:
const key = 'name'; console.log(person[key]); // 输出:Alice
注意:访问对象上不存在的属性,得到的结果是underfined, 不会报错
二、增加对象属性和方法
要增加对象的属性和方法,可以直接使用点语法或方括号语法赋值。例如:
const car = {};
// 增加属性
car.make = 'Toyota';
car.model = 'Camry';
car.year = 2023;
// 增加方法
car.start = function() {
console.log('Car is starting...');
};
console.log(car); // 输出:{ make: 'Toyota', model: 'Camry', year: 2023, start: [Function: start] }
car.start(); // 输出:Car is starting...
三、删除对象的属性和方法
要删除对象的属性和方法,可以使用 delete
操作符。例如:
const car = {
make: 'Toyota',
model: 'Camry',
year: 2023,
start: function() {
console.log('Car is starting...');
}
};
// 删除属性
delete car.year;
console.log(car); // 输出:{ make: 'Toyota', model: 'Camry', start: [Function: start] }
// 删除方法
delete car.start;
console.log(car); // 输出:{ make: 'Toyota', model: 'Camry' }
使用 delete
操作符可以完全移除对象中的属性或方法,但要注意这并不会释放内存。如果对象包含大量属性和方法,使用 delete
可能会影响性能。在实际应用中,应谨慎使用 delete
操作符。
创建对象
当我们在JavaScript中创建对象时,通常有几种方式可以选择。
一. 创建对象字面量
对象字面量是最简单和最直接的方法来创建对象。它允许我们在大括号中定义对象的属性和方法。
// 创建对象字面量
const person = {
name: 'John',
age: 30,
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
};
// 调用对象方法
person.greet(); // 输出:Hello, my name is John and I'm 30 years old.
二. 调用系统自带的构造函数
JavaScript提供了一些内置的构造函数,如 Object
、Array
、Date
等,通过使用 new
关键字可以调用这些构造函数来创建对象。
// 调用系统自带的构造函数
const book = new Object();
book.title = 'JavaScript Cookbook';
book.author = 'John Doe';
book.pages = 300;
console.log(book); // 输出:{ title: 'JavaScript Cookbook', author: 'John Doe', pages: 300 }
三. 调用自定义的构造函数
除了系统自带的构造函数外,我们还可以自定义构造函数来创建对象。构造函数是一个普通的函数,通过使用 new
关键字来调用它,我们可以创建一个新的对象实例。
// 调用自定义的构造函数
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
this.drive = function() {
console.log(`The ${this.make} ${this.model} is driving.`);
};
}
// 创建Car对象实例
const myCar = new Car('Toyota', 'Camry', 2020);
console.log(myCar); // 输出:Car { make: 'Toyota', model: 'Camry', year: 2020, drive: [Function] }
myCar.drive(); // 输出:The Toyota Camry is driving.
在上面的示例中,我们定义了一个名为 Car
的构造函数,它有三个参数:make
、model
和 year
。在构造函数内部,我们使用 this
关键字来指代新创建的对象实例,并分配属性和方法。通过调用 new Car(...)
来创建 myCar
对象实例,并使用 myCar.drive()
方法来调用对象的方法。
构造函数 new的解释过程:
- new 会在构造函数中创建一个this
- 执行构造函数中的逻辑代码,相对于给this添加属性和方法
- 返回this对象
答疑
var num = 123;
num.abc = 'abc';
console.log(num.abc);
通过上述讲解你是不是已经对对象有了一个基本的认识!但是数字类型不是对象,为什么添加属性不会发生报错呢?
在 JavaScript 中,数字是基本数据类型,但在访问其属性时,V8引擎会临时
将其转换为包装对象。
因此,当你尝试给数字添加属性时,JavaScript 会临时创建一个临时对象
,给这个对象添加属性,但这个属性只在这个临时对象上有效,对原始的数字没有影响。所以虽然不会报错,但实际上添加的属性并不会对原始数字产生影响。(所以才说“貌似”对象,但不会改变)
你也可以这样去理解过程:
//包装类
//V8引擎把num创建成了一个对象,并给其添加了属性
new Number(123).abc = 'abc'
//但是V8复查时发现并不是想把它作为对象来使用,所以又删除了它的属性
delete new Number(123).abc
//所以打印对象不存在的属性时就会出现underfined的结果
console.log(new Number(123).abc);
对比分析
我们再来思考一下下面这个代码打印的结果是什么?
var num = new Number(123);
num.abc = 'abc';
console.log(num.abc);
这段代码会打印出 'abc'
。因为 num
是一个包装了数字的对象,你可以给对象添加属性。
在前一个例子中,num
是一个基本数据类型的数字,而在第二个例子中,num
是一个包装了数字的对象。虽然两者在语法上很相似,但在底层实现上有所不同。
在第一个例子中,当你尝试给基本数据类型的数字添加属性时,JavaScript 引擎会临时将其转换为包装对象,给临时对象添加属性。这种转换是临时的,不会对原始数据类型产生影响。
而在第二个例子中,你显式地创建了一个包装了数字的对象,这个对象本身就是一个完整的 JavaScript 对象,你可以向它添加属性,这些属性会被对象保留,与原始数据类型本身无关。
你也可以这样去理解过程:
//也就是说V8复查时是把它作为对象来使用,所以没有删除了它的属性
//这个也可以
console.log(num * 2); //结果246
//因为是包装了数字的对象,所以在参与运算时, V8认为它是数字
上难度,给出面试题
这是一个大厂面试题,欢迎小伙伴在评论区留言解答
var str = 'abc'
str += 1
var test = typeof (str)
if (test.length == 6) {
test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);
//这个结果是什么
最后
在学习过程中,我们常常知其然而不知其所以然,尤其对于弱语言,有太多需要我们去深入其内核本质的地方,保持追溯本源的态度才能百战不殆!
小编同样将继续学习,继续分享,喜欢的小伙伴不要忘了一键三连哦!
转载自:https://juejin.cn/post/7365694439569113128