Home >Web Front-end >JS Tutorial >Detailed explanation of properties and characteristics in JavaScript

Detailed explanation of properties and characteristics in JavaScript

黄舟
黄舟Original
2016-12-13 16:57:551117browse

Attributes and characteristics in JavaScript are two completely different concepts. Here I will use what I have learned to deeply understand the attributes and characteristics in JavaScript.

The main content is as follows:

Understand the nature of objects in JavaScript, the relationship between objects and classes, and the relationship between objects and reference types

How to classify object attributes

Understanding the characteristics of attributes

Part 1: Understanding JavaScript The essence of objects, the relationship between objects and classes, and the relationship between objects and reference types

The essence of objects: ECMA-262 defines an object as: a collection of unordered attributes, whose attributes can include basic values, objects or functions. That is, an object is a set of values ​​in no particular order. Each property or method of the object has a name, and this name maps to a value. Therefore, the essence of an object is a hash table: it is a set of name-value pairs, and the values ​​can be data or functions.

The relationship between objects and classes: In JavaScript, objects and classes have no relationship. This is because there is no concept of classes at all in ECMAScript, and its objects are different from those in other class-based languages.

The relationship between objects and reference types: Objects and reference types are not equivalent because each object is created based on a reference type.

Part 2: How to classify object properties

Objects created by constructors or object literal methods have properties and methods (as long as properties and methods are mentioned, they must belong to the object; as long as the object is mentioned, it It must have attributes and methods (except customization)), among which attributes can be divided into data attributes and accessor attributes. Their differences are as follows:

Data attributes are generally used to store data values, and accessor attributes do not contain data values.

Accessor attributes are mostly used for get/set operations

Part 3: Understanding the characteristics of attributes

ECMAScript defines the concept of attributes in order to describe the various characteristics of object attributes (properties). That is to say, characteristics are different from attributes. Characteristics are used to describe attributes. Below, I will explain respectively:

Data properties and their characteristics

Accessor properties and their characteristics

How to use the Object.defineProperties() method to define multiple properties

How to use the Object.getOwnPropertyDescripter() method to read properties Descriptor to read the characteristics of the attribute

1. Data attribute and its characteristics

Just now we said that the data attribute is used to store data values, so the data attribute has a data value position at which it can be read and write the value. The data attribute has 4 characteristics that describe its behavior. Since ECMAScript stipulates that the characteristics of the attribute cannot be directly accessed in JavaScript (note: it is not inaccessible), so we put it in two sets of square brackets. As follows:

[[Configurable]]: The default value is true, a. Indicates whether the attribute can be redefined by deleting the attribute through delete. b. Whether the characteristics of the attribute can be modified. c. Ability to change attributes from data attributes to accessor attributes

[[Enumerable]]: The default value is true, indicating whether the attribute can be returned through a for-in loop (so: if it is false, then the for-in loop does not method to enumerate the properties where it is located)

[[Writable]]: The default value is true, indicating whether the value of the property can be modified. This is different from [[Configurable]].

[[Value]]: The default value is undefined. This value is the attribute value of the attribute. We can read the attribute value at this position and write the attribute value at this position.

Note: The above default refers to the properties owned by the object created through the constructor or object literal, not the Object.defineProperty() method to be introduced below

These properties all have default values, but if these default The value is not what we want, what should we do? Of course it’s a modification! We can modify the default properties of the property through the Object.defineProperty() method. English defineProperty means defining properties. This method receives three parameters: the object where the property resides, the name of the property, and a descriptor object. The third parameter descriptor object is created by the object literal method, and the attributes and attribute values ​​inside actually store the characteristics and attribute values ​​to be modified.

Let’s use a few examples to understand in depth.

a

var person={};
Object.defineProperty(person,"name",{
  writable:false,
  value:"zhuzhenwei"
});
console.log(person.name);//zhuzhenwei
person.name="heting";
console.log(person.name);//zhuzhenwei

Here I created an object using the object literal method, but did not create methods and properties at the same time. Instead, the Object.defineProperty() method is used to create properties and modify default values. Here writable is set to false, so when I try to modify person.name later, it is invalid.


b

var person={};
Object.defineProperty(person,"name",{
  value:"zhuzhenwei"
});
console.log(person.name);//zhuzhenwei
person.name="heting";
console.log(person.name);//zhuzhenwei

Pay attention to this example. In this example, I deleted writable:false. Why can't I modify it? This is because when I introduced the features before, the first three defaulted to true, which was obtained when the object was created and the properties were created. For properties created by calling the Object.defineProperty() method, the default values ​​of the first three properties are false. Please note here.


c

var person={};
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
  configurable:false
});
console.log(person.name);//zhuzhenwei
delete person.name;
console.log(person.name);//zhuzhenwei

Here we set the property of the newly created attribute name to configurable:false; therefore the following operation of deleting the attribute is invalid. According to b, it can be seen that configurable, the default is false, and cannot be modified even if it is removed.


d

var person={};
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
  configurable:true
});
console.log(person.name);//zhuzhenwei
delete person.name;
console.log(person.name);//undefined 

在这里我将默认的configurable的值由默认的false修改为了true,于是变成了可配置的,那么最后就成功删除了。

e

var person={};
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
  configurable:false
});
console.log(person.name);//zhuzhenwei
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
  configurable:true
});
console.log(person.name);//Uncaught TypeError: Cannot redefine property: name(…)

如果之前已经设置成为了false,那么后面再改成true也是徒劳的,即:一旦把属性设置成为不可配置的,就不能再把它变回可配置了。


f

console.log(person.name);//Uncaught TypeError: Cannot redefine property: name(…)
var person={};
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
});
console.log(person.name);//zhuzhenwei
Object.defineProperty(person,"name",{
  value:"zhuzhenwei",
  configurable:true
});
console.log(person.name);//Uncaught TypeError: Cannot redefine property: name(…)

   

这里可以说明,即使前一步我们不管默认的configurable:false,后面得到的仍是不可配置。于是,可以得出结论,为了可配置,必须在第一次调用Object.defineProperty()函数时就将默认的值修改为true。

2.访问器属性及其特性  

之前提到,访问器属性不包含数据值,他们包含一对getter函数和setter函数(这两个函数不是必须的)。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性是,会调用setter函数并传入新值,这个函数负责决定如何处理数据。同样,由于不能通过JavaScript来直接访问得到访问器属性的特性,所以下面列出的特性将由[[]]括起来以作区分。

[[Configurable]]:默认值为true,a、表示能否通过delete删除属性从而重新定义属性 b、能否修改属性的特性 c、能够把属性由访问器属性修改为数据属性

[[Enumerable]]:默认值为true,表示能否通过for-in循环返回该属性(所以:如果为false,那么for-in循环没法枚举它所在的属性)

[[Get]]:在读取属性时调用的函数。默认值为undefined  关键:特性可以是一个函数

[[Set]]:  在写入属性时调用的函数。默认值为undefined 关键:特性可以是一个函数 由于get和set函数也属于属性的特性,那么他们就有可能(说有可能是因为这两个函数也不是必须的)出现在Object.defineproperty的第三个参数描述符对象的属性中。

注意:1.相对于数据属性,我们发现访问器属性中没有writable特性和value特性。这是因为访问器属性不包含数据值,那么我们怎么当然就不可修改属性的值(用不到writable特性),更不用考虑value了。

   2.访问器属性不能直接定义,必须是用Object.defineProperty()来定义。(通过这个规定我们就能准确地判断出访问器属性和数据属性了)

通过下面这个例子来深入理解:

var book={
  _year:2004,
  edition:1
};
Object.defineProperty(book,"year",{
  get:function(){<br>            return this._year;
  },
  set:function(newValue){
    if(newValue>2004){
      this._year=newValue;
      this.edition+=newValue-2004;
    }
  }
});
book.year=2005;
console.log(book.edition);//2

   

几个需要深入理解的地方:

1.访问器属性不能直接定义,必须使用Object.defineProperty()来定义,且该属性具有set和ger特性,于是可以判断,_year和edition是数据属性,而year是访问器属性。

2.我们看到_year这个数据属性前面是以_(下划线)开头的,这个一种常用的记号,用于表示只能通过对象方法访问的属性。从上面的例子中可以看到get相当于描述符对象的一个方法,而_year正是在这个对象方法访问的属性。而edition既可以通过对象方法访问,也可以由对象直接访问。

3.book.year表示正在读取访问器属性,这时会调用get函数,并返回了2004这个有效的值。

4.book.year=2005表示写入访问器属性,这时会调用set函数并传入新值,即将2005传给newValue,这个函数决定如何处理数据。

5.这时使用访问器属性的常见方法-即设置一个属性的值会导致其他属性发生变化。


3.如何利用Object.defineProperties()方法定义多个特性

显然,一个对象不可能只具有一个属性,因此,定义多个属性的可能性很大,于是JavaScript提供了Object.defineProperties()方法解决这个问题。这个方法接收两个参数,第一个是要定义属性所在的对象,第二个是一个对象字面量方法创建的对象,对象的属性名即为要定义的特姓名,对象的属性值又是一个对象,这个对象里的属性名和属性值分别是特性名和特性值(这里不是很好理解,看例子即可)。

var book={};
Object.defineProperties(book,{
  _year:{
    writable:true,
    value:2004
  },
  edition:{
    writable:true,
    value:1
  },
  year:{
    get:function(){
      return this._year;
    },
    set:function(){
      if(newValue>2004){
        this._year=newValue;
        this.edition+=newValue-2004;
      }
    }
  }
}); 

4.如何利用Object.getOwnPropertyDescripter()方法读取属性的描述符以读取属性的特性

  我们可以使用Object.getOwnPropertyDescripter()方法来取得给定属性的描述符。getOwnPropertyDescripter即为取得自身属性描述符的意思。这个方法接收两个参数:属性所在的对象要要读取其描述符的属性名称。返回一个对象。

  对于访问器属性而言,这个对象的属性有configurable、enumerable、get和set;

  对于数据属性而言,这个对象的属性有configurable、enumerable、writable和value。

var book={};
Object.defineProperties(book,{
  _year:{
    value:2004
  },
  edition:{
    value:1
  },
  year:{
    get:function(){
      return this._year;
    },
    set:function(){
      if(newValue>2004){
        this._year=newValue;
        this.edition+=newValue-2004;
      }
    }
  }
});
var descriptor=Object.getOwnPropertyDescriptor(book,"_year");
console.log(descriptor.value);//2004
console.log(descriptor.configurable);//false 因为通过Object.defineProperties()方法创建的属性的特性configurable enumerable都是false
console.log(typeof descriptor.get);//undefined 注意:这是数据属性,是不具有get特性的
var descriptor=Object.getOwnPropertyDescriptor(book,"year");
console.log(descriptor.value);//undefined
console.log(descriptor.enumerable);//false
console.log(typeof descriptor.get);//function get虽然是属性的一个特性,但是它也是函数

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时想要关注更多的相关内容请关注PHP中文网(www.php.cn)!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn