>웹 프론트엔드 >JS 튜토리얼 >JavaScript의 객체 속성에 대한 자세한 설명

JavaScript의 객체 속성에 대한 자세한 설명

angryTom
angryTom앞으로
2019-11-28 17:37:252951검색

JavaScript의 객체 속성에 대한 자세한 설명

JavaScript의 객체 개념은 실제로 혼란스러울 수 있습니다. 다음 예를 보세요:

var strPrimitive = "I'm mamacat";
typeof strPrimitive; // "string"
strPrimitive instanceof String; // false

var strObject = new String("I'm mamacat");
typeof strObject; // "object"
strObject instanceof String; // true

strPrimitive.substr(8, 3); // "cat"

동일한 문자열이 객체에 할당됩니다. 때로는 문자열 유형이고 때로는 객체이지만 분명히 객체 유형이 아닌 변수는 여전히 객체를 사용할 수 있습니다. 속성입니다. 왜 그렇습니까?

【관련 강좌 추천: JavaScript 비디오 튜토리얼

유형 및 내장 객체#🎜🎜 ## 🎜🎜#JavaScript에는

string, number, boolean, null, undefine 및 object

등 6가지 주요 (언어) 유형이 있으며, 그 중 처음 5가지 기본 유형은 객체가 아닙니다(typeof null 당신이 얻는 것은 언어 자체의 버그인 "객체"입니다. 이 외에도 배열, 함수, 내장 객체 등 특수한 객체 하위 유형이 많이 있습니다. 일부 내장 객체의 이름은 String, Boolean, Object 등과 같은 단순한 기본 유형과 동일하게 보입니다. 표현 측면에서 이러한 내장 객체는 다른 객체지향 언어의 "클래스" 개념과 유사합니다. 실제로는 해당 객체를 구성하는 데 사용할 수 있는 일부 내장 함수일 뿐입니다. 하위 유형(혼란하지 마세요), 함수도 객체이므로 여기에는 모순이 없습니다. 따라서 원래의 예로 돌아갈 수 있습니다. strObject는 내장 함수/내장 객체 String에 의해 생성된 변수이며 String 하위 유형에 해당하므로 객체이고 strPrimitive는 기본 리터럴 값일 뿐입니다.

물론 위 예시의 하단에서는 strPrimitive에서 substr() 함수를 호출하는 것처럼 보입니다. 이는 JavaScript 엔진이 필요할 때 원본 리터럴을 해당 객체로 변환하고, 변환 후에는 자연스럽게 속성을 사용하여 해당 메서드에 액세스할 수 있습니다.

Object Properties

그래서 위의 예에서 String 객체 인스턴스에는 substr() 함수를 사용할 수 있지만 As에 따르면 이전 기사에서 알 수 있듯이 이러한 "함수" 자체는 개체에 속하지 않지만 이러한 함수는 본질적으로 해당 개체의 속성입니다. 물론, 어떤 종류의 객체 자체가 다양한 속성을 가지고 있다고 하더라도 실제로는 이러한 속성이 대부분 독립적으로 존재하지만 단지 참조의 형태로 서로 연관되어 있을 뿐이라는 것은 앞서 배운 내용과 모순되지 않습니다. 이와 관련된 것들을 객체의 속성이라고 합니다.

사물 사본

간단한 보고서 삽입, 이전 기사에서도 언급했지만 위에서 반복적으로 강조한 내용은 다음과 같습니다. 속성은 속성의 형태로 관련된 독립적인 존재로만 참조됩니다. 우리는 때때로 속성이 개체의 일부라고 "당연히 여깁니다". 문제가 발생하기 가장 쉬운 곳 중 하나는 개체를 복사하는 것입니다. 주의 깊게 생각해 보면 객체를 복사할 때 해당 속성 자체는 참조 연관일 뿐이므로 "복사된" 객체에 포함된 속성 참조는 실제로 원본 객체의 속성 참조와 동일한 위치를 가리킨다는 것을 알 수 있습니다. :

var ori = { a : 1};
var ori_copy = ori;
ori.a = 61;
ori_copy.a; // 61

분명히 이는 우리의 기대와 다를 수 있으며, 객체를 실제로 복사하려는 경우 완벽하게 적용할 수 있는 솔루션은 없는 경우가 많습니다. 객체를 직렬화하는 것이 일반적인 관행입니다. 그런 다음 직렬화하여 개체를 복사할 새 개체를 가져옵니다(예: json 사용).

은 객체의 얕은 복사본을 수행하기 위해 ES6에 추가되었습니다. 이 방법은 객체의 모든 열거 가능한 속성을 등호를 사용하여 새 객체에 할당하는 것입니다. 그러나 등호 할당은 속성(속성 설명자, 나중에 설명함)의 메타 정보를 할당하는 것이 아니므로 필요한 경우 특별히 주의해야 합니다.

Object.assign()

속성 액세스 및 배열

객체와 관련된 속성에 액세스하는 방법은 . 또는 [] 연산자인 obj.a를 사용하는 것입니다. obj["a"]에 의해 액세스되는 속성은 본질적으로 동일하며, 이 두 액세스 형식의 유일한 차이점은 액세스되는 속성 이름에 이상한 기호가 있을 수 있는지 여부입니다. [] 연산자에 던져지는 것은 실제로 문자열입니다. 물론 이 개념에서 놀라운 점은 배열에 대한 첨자 액세스도 예외가 아니라는 것입니다. 숫자는 사용되기 전에 문자열로 변환됩니다.

// 对象的属性访问:
var tejilang = {1 : "Teji Wolf"};
tejilang instanceof Array; // false
tejilang["1"]; // "Teji Wolf"
tejilang[1]; // "Teji Wolf"

// 这回保证它是 Array
var macat = ["codingcat"];
macat instanceof Array; // true
macat.length; // 1
macat[0]; // "codingcat"
macat["0"]; // "codingcat"
macat.length = 20;
macat; // (20) ["codingcat", empty × 19]

数组下标既然不属例外情况,那数组对象必然有其它属性控制数组本身的行为,例如上例中,macat 数组的长度就是 length 属性所体现的,通过修改它的值也就改变了对象本身对外的表现形式。当然,由于数组本身就是对象,所以我们还是可以把数组当键值对来用,只是这种做法通常是没有意义且会让人感到困惑的。JavaScript 引擎通常都根据对象的类型做了不同程度的优化,故除了代码逻辑可读性外,合理的使用也是多少可以改善性能的。

能够通过字符访问属性还是存在一些别的好处的,比如 ES6 的可计算属性名。当然 ES6 不在本文的关注范围内,所以这里就不再讨论了。

属性描述符

有时我们可能不希望某个属性被随意修改,有时候我们需要额外配置一些属性的信息,自 ES5 起,所有的属性就都具备了“属性描述符”(Property Descriptor)来控制属性本身的这些元信息。

数据描述符

来看这个例子:

var chris = {};
Object.defineProperty(chris, "IQ", {
    value: 228,
    writable: false,
    configurable: true,
    enumerable: true
});
chris.IQ = 61; // 静默失败了,如果是严格模式则会 TypeError
chris.IQ; // 228

通过 defineProperty 可以对一个对象的属性配置其对应的属性描述符(元信息),而属性描述符则包含访问描述符和数据描述符,上面的例子中,defineProperty 的第三个参数就定义了数据的若干数据描述符,其中 writable 表示可写,configurable 表示属性是否可配置(注意,修改成不可配置是单向操作),enumerable 则表示属性是否应当出现在枚举中,比如 for..in 中。

显然我们可以通过属性描述符实现对属性的保护,而同时也存在一些方便函数来做近似的事。如 Object.preventExtensions() 会保留原有属性但禁止添加新属性,Object.seal() 会密封对象,在禁止添加新属性的基础上把原有属性标记为不可配置,Object.freeze() 会冻结对象,即在密封的基础上把数据访问属性标记为不可写。

[[Get]], [[Put]] 和访问描述符

在我们访问和赋值一个对象的属性时,实际上是通过 [[Get]] 和 [[Put]] 操作进行的,例如属性访问时,[[Get]] 会先找有没有这个属性,如果没有则会遍历对象的 [[Prototype]] 链(原型链,这次不谈这个概念)来找,实在找不到则返回 undefined 。而这个行为实际是允许我们通过设置 getter (get())和 setter (set())函数来改变的,它们被称为 访问描述符。

当我们提供访问描述符时,对应的访问操作就不再受到 value writable 属性的影响了,另外需要注意的是,尽管它们也是属性描述符,但定义 getter 和 setter 并不要求一定要通过 defineProperty 设置:

var obj = {
    get a() { // 给 a 属性定义 getter
        return this._a_;
    },
    set a(val) { // a 属性的 setter
        this._a_ = val * 2;
    }
}

obj.a = 2;
obj.a; // 4

属性存在性

因为属性的值也可能是 undefined,不存在的属性直接访问得到的也是 undefined,所以直接通过简单的属性访问是无法区分是否存在的,这时我们即可通过 in 或者 hasOwnProperty() 检查属性是否存在对象中了:

var obj = {a : 2};
"a" in obj; // true
obj.hasOwnProperty("a"); // true

尽管仍没有讲到原型链的概念,这里仍然应注意,in 操作符会检查原型链中是否存在属性,而 hasOwnProperty 则不会。另外在一些情况下,有的对象会没有 hasOwnProperty 这个属性(此处不提原因),这时可以用过 Object.prototype.hasOwnProperty.call(objName, propertyName) 来实现检查。

本文来自 js教程 栏目,欢迎学习!  

위 내용은 JavaScript의 객체 속성에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제