JavaScript中的数据类型

基本数据类型

  1. Number: 用于表示数字,包括整数和浮点数。
  2. String: 用于表示文本数据,以单引号或双引号包围。
  3. Boolean: 用于表示逻辑值,即 true 或 false。
  4. Null: 表示一个空值,该值是一个关键字,不是一个对象。
  5. Undefined: 表示未定义或未赋值的变量。
  6. Symbol: ES6 引入的数据类型,表示唯一的、不可变的值。
  7. BigInt: ES10 引入的数据类型,用于表示任意精度的整数。

复杂数据类型

  1. Object: 用于存储多个值的集合,可以通过名称访问其中的值。对象是由花括号{}包裹的键值对组成,也包括函数、数组、日期等。

在 JavaScript 中,通过 typeof 操作符可以获取一个值的数据类型。例如:

1
2
3
4
5
6
7
8
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof null; // "object" (这是一个历史遗留问题,实际上null的类型是null)
typeof undefined; // "undefined"
typeof Symbol("symbol"); // "symbol"
typeof 100n; // "bigint"
typeof {}; // "object"

JavaScript 的数据类型较为灵活,开发者需要了解各种数据类型的特性和使用场景,以便在编程中合理地处理和操作不同类型的数据。

JavaScript中的proto和prototype详细介绍

__proto__

  • __proto__ 是每个 JavaScript 对象都具有的一个属性,它指向了该对象的原型。实际上,__proto__ 属性是访问对象原型的 getter/setter 方法。

  • 通过 __proto__ 属性,我们可以在运行时动态地获取和修改一个对象的原型链。

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let animal = {
    eats: true,
    };

    let rabbit = {
    jumps: true,
    };

    rabbit.__proto__ = animal;

    console.log(rabbit.jumps); // true
    console.log(rabbit.eats); // true

prototype

  • prototype 是函数对象特有的属性,在创建一个函数时,该函数会自动获得一个名为 prototype 的属性。

  • 当我们使用关键字 new 来创建一个实例时,这个实例的 __proto__ 会指向其构造函数的 prototype

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    function Animal(name) {
    this.name = name;
    }

    Animal.prototype.eats = true;

    let rabbit = new Animal("Rabbit");
    console.log(rabbit.eats); // true

总结来说,__proto__ 是每个对象实例都有的内部属性,用于访问其原型;而 prototype 是函数对象特有的属性,用于构建由该函数创建的实例的原型链。JavaScript 中的原型链机制基于这两个概念,它们共同构成了 JavaScript 中对象之间继承关系的基础。

Vue中组件传值的方法总结

在 Vue 中,组件之间的数据传递是常见的需求。以下是常用的组件传值方法:

  1. props

    使用 props 可以从父组件向子组件传递数据,通过在子组件中定义 props 属性来接收父组件传递的数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- ParentComponent.vue -->
    <template>
    <ChildComponent :message="parentMessage" />
    </template>

    <script>
    import ChildComponent from './ChildComponent.vue';

    export default {
    components: {
    ChildComponent,
    },
    data() {
    return {
    parentMessage: 'Hello from parent!',
    };
    },
    };
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- ChildComponent.vue -->
    <template>
    <p>{{ message }}</p>
    </template>

    <script>
    export default {
    props: ['message'],
    };
    </script>
  2. $emit

    子组件可以通过$emit 触发一个自定义事件,并将数据传递给父组件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!-- ChildComponent.vue -->
    <template>
    <button @click="sendMessageToParent">Send Message to Parent</button>
    </template>

    <script>
    export default {
    methods: {
    sendMessageToParent() {
    this.$emit('message-to-parent', 'Hello from child!');
    },
    },
    };
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- ParentComponent.vue -->
    <template>
    <ChildComponent @message-to-parent="handleMessageFromChild" />
    </template>

    <script>
    import ChildComponent from './ChildComponent.vue';

    export default {
    components: {
    ChildComponent,
    },
    methods: {
    handleMessageFromChild(message) {
    console.log(message);
    },
    },
    };
    </script>
  3. provide/inject

    使用 provide/inject 可以在祖先组件提供数据,然后在子孙组件中注入获取数据。

    1
    2
    3
    4
    5
    6
    7
    8
    <!-- AncestorComponent.vue -->
    <script>
    export default {
    provide: {
    sharedData: 'Hello from ancestor!',
    },
    };
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- DescendantComponent.vue -->
    <template>
    <p>{{ sharedData }}</p>
    </template>

    <script>
    export default {
    inject: ['sharedData'],
    };
    </script>

这些方法提供了灵活的方式来在 Vue 组件之间进行数据传递,开发者可以根据具体场景选择合适的方式进行组件间数据传递。

JavaScript中的for...in和for...of循环对比分析

for…in 循环

  • 特点:

    • 循环遍历对象的可枚举属性,包括自身和原型链上的属性。
    • 可以用于遍历对象的属性,不建议用于数组遍历。
  • 示例

    1
    2
    3
    4
    const obj = { a: 1, b: 2, c: 3 };
    for (let key in obj) {
    console.log(key, obj[key]);
    }

for…of 循环

  • 特点:

    • 用于遍历可迭代对象(如数组、字符串、Map、Set 等),支持迭代器协议。
    • 只会遍历可迭代对象自身的元素,不包括原型链上的属性。
  • 示例

    1
    2
    3
    4
    const arr = [1, 2, 3];
    for (let item of arr) {
    console.log(item);
    }

对比分析

  • 适用对象

    • for…in 适用于遍历对象的属性,而 for…of 适用于遍历可迭代对象的元素。
  • 遍历顺序

    • for…in 遍历的顺序不确定,可能不按照属性插入的顺序;for…of 按照对象的迭代顺序进行遍历。
  • 遍历内容

    • for…in 遍历对象的属性,包括继承的属性;for…of 只遍历对象自身的元素。
  • 性能

    • for…of 比 for…in 更高效,因为 for…of 只涉及迭代对象的元素。

根据需求选择合适的循环方式,for…in 适用于遍历对象属性,for…of 适用于遍历可迭代对象的元素。注意在遍历数组时,推荐使用 for…of 而不是 for…in。

Vue 2和Vue 3的Virtual DOM和Diff算法对比分析

特点 Vue 2 Vue 3
Virtual DOM 基于 snabbdom 实现 使用了全新的 Virtual DOM 实现
Diff 算法 基于双端比较算法 引入了优化过的静态树提升和动态响应式更新
静态树提升 不支持静态树提升 支持将动态生成的内容转换为静态节点,提高性能和减少更新开销
动态响应式更新 较为简单 通过观察者模式进行更精细的响应式更新

在 Vue 2 中,Virtual DOM 是基于 snabbdom 实现的,并且使用了双端比较算法进行 diff 操作。然而,Vue 2 不支持静态树提升,这使得动态生成的内容无法转换为静态节点,从而影响性能和增加更新开销。此外,Vue 2 的动态响应式更新相对较为简单。

相比之下,在 Vue 3 中引入了全新的 Virtual DOM 实现,并且改进了 Diff 算法,引入了优化过的静态树提升和动态响应式更新。Vue 3 支持将动态生成的内容转换为静态节点,以提高性能并减少更新开销。另外,Vue 3 通过观察者模式进行更精细的响应式更新,使得动态响应式更新更加灵活和高效。