原始值不具有属性。str.length :???

73 阅读3分钟

数据类型

JavaScript中的数据类型主要分为原始类型和引用类型。原始类型的值直接存在调用栈中,而引用类型的值存在堆中,而调用栈中存放的仅是堆中的引用地址。

e51bb8e8aeadc5559fc2211815998b4.jpg 按正常逻辑说我先把a赋给了b,再去修改了a中的age,打印b.age应该得到18。但是得到的却是20,是因为它们都是通过同一个地址找到的age,age的存放地址是不变的。

原始类型

原始类型包括:

  • String(字符串)
  • Number(数字)
  • Boolean(布尔值)
  • Null(空值)
  • Undefined(未定义)
  • Symbol(符号,ES6新增)

原始类型的特点是它们是不可变的,即一旦创建,就不能被修改。

引用类型

引用类型包括:

  • Object(对象)
  • Array(数组)
  • Function(函数)
  • Date(日期)
  • RegExp(正则表达式)
  • 等其他自定义对象

引用类型的值是对象,存储在堆中,而在调用栈中存放的只是堆中的引用地址。这意味着引用类型的赋值实际上是复制了引用,而非对象本身。

对象

对象是JavaScript中的一种引用类型,用于存储和组织数据。对象可以通过多种方式创建。

创建对象

  1. 对象字面量

    let person = {
      name: 'John',
      age: 30,
      isStudent: false
    };
    
  2. new Object()

    let person = new Object();
    person.name = 'John';
    person.age = 30;
    person.isStudent = false;
    
  3. 自定义构造函数

    function Person(name, age, isStudent) {
      this.name = name;
      this.age = age;
      this.isStudent = isStudent;
    }
    
    let person = new Person('John', 30, false);
    

构造函数

构造函数是一种特殊的函数,用于创建对象。它是一种工厂,可以批量生成具有相似属性和方法的对象。

new的过程

使用new关键字调用构造函数的过程包括:

  1. 创建this空对象

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    let person = new Person('John', 30);
    // 在这个过程中,JavaScript会创建一个空对象,并将其赋给this
    
  2. 执行构造函数中的逻辑

    function Person(name, age) {
      this.name = name;
      this.age = age;
      this.sayHello = function() {
        console.log(`Hello, my name is ${this.name}`);
      };
    }
    
    let person = new Person('John', 30);
    // 在这一步,构造函数中的逻辑被执行,为对象添加属性和方法
    
  3. 返回this对象

    function Person(name, age) {
      this.name = name;
      this.age = age;
      this.sayHello = function() {
        console.log(`Hello, my name is ${this.name}`);
      };
    }
    
    let person = new Person('John', 30);
    // 最终,构造函数返回创建的对象(this对象)
    

不难理解,构造函数得到的实例化对象之间是相互独立的。例如

function Car(color){
    this.name = 'BMW'
    this.height = 1400
    this.lang = 4900
    this.weight = 1000
    this.color = color
}

let car = new Car('green') //实例对象 == this
let car2 = new Car('red') 

car.name = '幻影'

打印car得到

image.png 打印car2得到

image.png

包装类

包装类是原始类型和对象之间的一种桥梁。原始值是不能具有属性和方法的,属性和方法是对象独有的。为了在原始类型上调用方法,JavaScript会临时将原始值转换为对应的包装类对象。

var num = 123
num.a = 'hello'
console.log(num.a);  //undefined
//因为原始类型是不能具有属性的

在js的v8引擎中,以上代码会被这样执行。这就是为什么得到undefined。

var num = new Number(123)
num.a = 'hello'
delete num.a
console.log(num.a);

考点:

var arr = [1,2,3,4]
arr.length = 2
console.log(arr);//并不会得到[1,2]
console,log(arr.length)//4

为什么下面的打印会得到4呢?不是不能有属性吗?

因为这里的length是官方内置的属性,它就是可以读到数组的长度。

需要注意的是,包装类对象是临时创建的,对原始值的修改并不会影响原始值本身。

深入理解JavaScript的数据类型和对象创建过程,对于编写高效且可维护的代码是至关重要的。通过合理地使用原始类型和引用类型,以及灵活运用构造函数和对象字面量,可以更好地组织和管理代码。

3333.jpg