MST

星途 面试题库

面试题:JavaScript 数据类型转换与隐式类型转换 - 专家难度

在 JavaScript 严格模式下,`Object.defineProperty` 定义的属性 `getter` 和 `setter` 中,进行隐式类型转换时会遵循哪些特殊规则?请举例说明,并阐述与非严格模式下的区别。同时分析在复杂对象嵌套结构中,这些规则如何影响数据的读写与类型转换。
26.2万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

严格模式下 Object.definePropertygettersetter 隐式类型转换规则

  1. 严格性要求:严格模式下,gettersetter 函数在处理隐式类型转换时遵循更严格的规则。例如,getter 必须返回一个值,如果没有显式返回,将返回 undefined,而不会像非严格模式下尝试进行隐式类型转换。
    • 示例
    'use strict';
    let obj = {};
    Object.defineProperty(obj, 'prop', {
        get: function () {
            // 没有显式返回值,严格模式下返回 undefined
        },
        set: function (value) {
            this._prop = value;
        }
    });
    console.log(obj.prop); // 输出 undefined
    
  2. setter 中的类型转换setter 函数接收的值会遵循基本的 JavaScript 类型转换规则,但不会进行某些宽松的隐式转换。例如,当设置属性值为 nullundefined 时,不会自动转换为其他类型。
    • 示例
    'use strict';
    let obj = {};
    Object.defineProperty(obj, 'prop', {
        get: function () {
            return this._prop;
        },
        set: function (value) {
            if (typeof value!=='string') {
                throw new TypeError('Value must be a string');
            }
            this._prop = value;
        }
    });
    try {
        obj.prop = null;
    } catch (e) {
        console.log(e.message); // 输出 'Value must be a string'
    }
    

与非严格模式下的区别

  1. getter 返回值:在非严格模式下,如果 getter 函数没有显式返回值,会尝试将函数内部的某些操作结果进行隐式类型转换作为返回值。例如,如果 getter 函数最后执行了一个表达式,可能会将该表达式的结果返回,即使没有 return 语句。而严格模式下,没有 return 语句则返回 undefined
    • 非严格模式示例
    let obj = {};
    Object.defineProperty(obj, 'prop', {
        get: function () {
            1 + 2; // 非严格模式下,该表达式结果可能被隐式返回
        },
        set: function (value) {
            this._prop = value;
        }
    });
    console.log(obj.prop); // 输出 3(非严格模式特殊行为)
    
  2. setter 类型宽松度:非严格模式下,setter 函数接收的值可能会进行更宽松的隐式类型转换。例如,即使 setter 期望一个字符串类型,传入 nullundefined 时可能不会报错,而是进行一些隐式转换(虽然不一定符合预期)。而严格模式下,更倾向于抛出类型错误。

在复杂对象嵌套结构中的影响

  1. 数据读取:在复杂对象嵌套结构中,严格模式下的 getter 规则确保了每个层级的属性读取都遵循预期的类型返回规则。如果某个嵌套对象的 getter 没有显式返回值,会明确返回 undefined,避免了非严格模式下可能出现的意外隐式返回值导致的数据读取错误。
    • 示例
    'use strict';
    let nestedObj = {};
    Object.defineProperty(nestedObj, 'inner', {
        value: {}
    });
    Object.defineProperty(nestedObj.inner, 'prop', {
        get: function () {
            // 没有显式返回值
        }
    });
    console.log(nestedObj.inner.prop); // 输出 undefined
    
  2. 数据写入setter 的严格类型转换规则在复杂对象嵌套结构中有助于保持数据的一致性。当向嵌套属性赋值时,严格模式下的 setter 会按照预期的类型转换规则处理值,如果不符合类型要求会抛出错误,防止错误的数据类型进入对象结构,而非严格模式下可能会允许一些不符合预期的类型转换,导致数据结构混乱。
    • 示例
    'use strict';
    let nestedObj = {};
    Object.defineProperty(nestedObj, 'inner', {
        value: {}
    });
    Object.defineProperty(nestedObj.inner, 'prop', {
        get: function () {
            return this._prop;
        },
        set: function (value) {
            if (typeof value!=='number') {
                throw new TypeError('Value must be a number');
            }
            this._prop = value;
        }
    });
    try {
        nestedObj.inner.prop = 'not a number';
    } catch (e) {
        console.log(e.message); // 输出 'Value must be a number'
    }
    

综上所述,严格模式下 Object.definePropertygettersetter 隐式类型转换规则更加严格,有助于编写更健壮、可预测的代码,特别是在复杂对象嵌套结构中,能有效避免因隐式类型转换导致的错误。