深入学习Javascript对象

在Javascript中,除了五种基本类型,即数字、字符串、布尔值、null、未定义的,它们都是对象,因此不理解对象并从中学习它们。


第一.

一个对象是聚集很多价值的复合价值(原始价值或其他对象),可以通过属性名来访问。属性名称可以包含一个空string.javascript对象的任意字符串,也可以称为一个数据结构,我们经常听到关于散列(Hash),哈希表(HashTable)、词典(字典)和关联数组(数组)。

在Javascript,对象可以分为三类:

(1)内置对象,如数组、函数、日期等。

这是主机对象,嵌入的Javascript解释器的宿主环境(如浏览器),如HtmlElement,等。

(3)自定义对象,也就是程序员使用代码来定义它。

一个对象的属性可以分为两类:

(自己的属性):直接在对象中定义的属性;

继承属性(继承的属性):对象原型对象中定义的属性(在原型对象下详细说明);

两。创建对象

既然是学习的对象,怎么能不理解如何创建一个对象呢面试中的学生可能会问你这个基本问题。

创建Javascript对象的两种方法是什么(或者:讨论创建Javascript对象的方式)

在这个问题上我被问了两次,有两种方法可以在互联网上创建对象,但是我有三种阅读的方式,现在我们来讨论这三种方式:

1。对象直接量

对象的直接数量由由几个名称/值对组成的映射表组成。名称/值在中间用冒号分隔,逗号在名称/值对之间用逗号分隔。整个映射表在括号里。属性名可以是Javascript标识符或字符串直接量,即以下两类的对象的创建是完全相同的:

var obj = { x 1,y 2 };

var obj = { x:1,Y 2 };

2。通过新创建对象

新操作符遵循一个函数调用,构造函数创建并初始化一个新对象:

1 var =新(对象);创建一个空对象,{。

2 var =新(数组);创建空数组,{ }。

3 var =新(日期);创建日期对象当前时间的表示形式

稍后讨论构造函数相关的内容。

3.object.create()

ecmascript5定义了一个方法叫object.create(),它创建了一个新的对象。第一个参数是对象的原型对象(似乎原型对象还没有被解释)。第二个可选参数用于进一步描述对象的属性,下面的第二个参数如下所述。因为这第三种方法是定义在ecmascript5。所以以前,你经常说有两种方法来创建对象,我想应该是原因:

1 VAR O1 = object.create({ x 1,y:2 }); / / O1对象继承的X和Y

2 VAR O2 = object.create(空); / /氧气没有原型

下面的三个完全相同:

1 var obj1 = { };

2 var obj2 =新的对象();

3 VAR OBJ3 = object.create(对象。原型);

为了解释为什么这三个完全相同,我们将用Javascript解释原型对象(嘿,让来宾等一下!)我记得一个伟大的神说:

Javascript是一种基于对象(对象)的语言,您遇到的每一件事物几乎都是一个对象,然而,它不是真正的面向对象编程语言,因为它的语法中没有类(类)。

面向对象编程语言javascript,没有类!!!那么,它是如何实现继承的呢是的,它通过原型对象。基本上,每个Javascript对象(除了null)都与另一个对象相关联,而另一个对象就是所谓的原型对象。原型对象也可以被称为一个原型,它不像想象的那样复杂,但也是一个对象,每个对象从原型对象继承属性和对象的原型属性(该属性在对象中的值是默认创建的自动的,不需要显示自定义)是原型对象的对象,obj.prototype对象是obj对象的原型。

原型对象首先说明了这个问题,并返回了对原型对象的理解的上述问题,下面是不需要解释太多的Javascript语言。

(1)object.prototype对象的原型对象,所有的对象都是直接由对象创建。

2。关键词新构造函数创建的原型对象是构造函数的原型属性的值,所以由构造函数对象创建对象的原型是Object.prototype。

也有第三种方式来创建对象,object.create()的第一个参数。

三。属性的查询和设置

仅仅学习如何创建一个对象是不够的,因为对象只有一些属性才能真正起作用,然后继续学习对象的属性!

通过点(。)或方括号({})操作符来获取和设置属性的值。对于点(。),右边必须是一个命名的属性名称(注:Javascript语言的标识符具有自己的法律规则,而不同于引用字符串);在方括号({}),方括号必须是一个字符串的字符串变量(当然你可以,其他的可以被转换成一个字符串值,如什么是数字会下降),这个字符串是属性的名称,如下面的示例:


var obj = { x 1,y 2 };
obj。x = 5;
obj { Y } = 6



在概要中提到的,Javascript的对象有自己的属性和继承属性。当X属性查询对象,首先会找对象obj具有X,财产如果没有,obj.prototype会找到原型对象是对象属性X,如果不是,那么obj.prototype.prototype会找到原型对象是obj.prototype X的性质,所以直到X或搜索找到原型对象定义对象为止。可以看出,很多原型对象继承一个对象。这些原型构成了一个链,这就是我们通常所说的原型链。这种继承也是Javascript原型继承。

上面提到的o查询对象属性将遵循原型链一步一步的搜索,但是属性值的设置只会修改属性(如果这个对象没有这个属性,它将添加这个属性,并且赋值)不会修改原型链的对象。

四。存取属性

我们以上所说的是一个很普通的对象的属性,称为数据属性和数据属性只有一个简单的价值。然而,在ECMAscript 5,属性值可以通过一个或两个方法所取代。两方法getter和setter和getter和setter,定义的属性称为访问器的属性(访问性能)。

当程序查询的访问属性的值,Javascript调用getter方法(无参数)。此方法的返回值的属性访问表达式的值,当程序集的访问属性的值,Javascript调用setter方法,通过价值分配的表达权侧为参数的二传手。如果物业也有getter和setter方法,那么这是一个读写属性;如果只有getter方法,那么它是只读属性分配一个只读属性,是不是一个错误,但没有成功;如果仅是setter方法,那么这是一个只写属性,读取只写属性始终返回未定义的。看到一个实际的前充足的:


var { { { {
X:1,
y:2,
R(){ return Math.sqrt(这个X,X + Y *这这。。Y);};
集R(价值){
var属性的旧值= Math.sqrt(这个X,X + Y *,,Y);
风险率=价值/属性的旧值;
这个,x =比;
这个,y =比;
},
得到θ(){ return(这math.atan2。Y,这。x);},
打印:函数(){ console.log(X:+,X,Y:+,Y);}
};



作为一个例子,存取属性定义了一个或两个函数具有相同名字的属性。函数定义不使用函数关键字,但使用GET和设置,也不使用冒号将属性名与函数体分开。相反,下面的打印属性是一个函数方法。Javascript将这些函数称为对象方法,也就是说,函数体中的这个函数引用这个对象:


作为控制台的输出,r、θ、x和y只是一个值属性,而打印是一个方法属性。

这个访问器,由ECMAscript 5增加,比普通的属性更复杂,但也使操作对象属性的密钥对更严格。

五。删除属性

鲍伯行和代码一般是实现增加和改变搜索功能的,它已经增加、修改、检查、删除下面的对话!

删除操作符可以删除对象的属性,它的操作数应该是一个属性访问表达式,但是,删除只是断开的属性和主机对象之间的连接,而不是属性中的属性:


var:{:{ 1 };
var;
删除一个P;



执行此代码后,对b.x的值仍为1。由于删除属性的引用仍然存在,有时这种不精确的代码会导致内存泄漏,所以当我们销毁对象时,我们应该通过属性中的属性并依次删除它们。

删除表达式返回true的情况:

(1)删除或没有任何副作用(如删除不存在的属性);

(2)如果删除不是后面的属性访问表达式;


var obj = { x:1,得到(R){ return 5;},集合R(价值){ x =价值;} };
删除对象X; / / X属性删除对象,则返回true
删除对象X; / /删除属性不存在,返回true
删除obj。R; / / R属性删除对象,则返回true
删除obj.tostring; / /无副作用(toString是遗传的,不能被删除),返回true
删除1;数字1不是属性访问表达式,返回true



删除表达式返回false的情况:

(1)删除配置(配置属性,特征为下面讨论)是虚假的属性;

删除object.prototype; / /返回false,原型是不可配置

通过var语句变量或函数语句的函数不是全局对象配置属性。

变量x=1;

删除这个x。

函数(f){ }

删除这个。

六。财产的性质

可配置的属性是上面提到的,因为以下概念属性和枚举属性也用。让我们先来讨论属性的属性。

此外,包括名称和值,性能也有三个特征,确定他们要写,枚举,和配置。这些属性不能设置在ECMAscript 3。所有的属性由ECMAscript 3创建的程序都是可写的,枚举和配置,以及这些属性不能修改。ECMAscript 5提供了一个API来查询和设置这些属性的属性。这些API库开发者非常有用,因为:

它可以通过API的原型对象添加方法,并设置为不可数,这使得它们更像是一个内置的方法;

通过定义不能修改或删除的属性,可以由这些API锁定对象。

这里我们考虑的访问属性的getter和setter方法属性。按照这个逻辑,我们也可以看看属性值的属性。因此,可以认为,一个属性包含一个名字和4个特点。一个数据的4个属性属性值(值)、写(写)(枚举,枚举),和可配置(配置)。访问器的属性不具有价值性和可写的,他们写的自然是由是否setter方法存在。因此,访问器的属性4属性(得到),读写(套),计数,和可配置性。

为了实现查询和设置属性操作,ECMAscript 5标准定义了一个对象的命名属性描述符,它代表的4个特征,属性的描述对象和属性所描述的是同一个名字。因此,对数据的属性描述对象的属性值,可写,可枚举,和可配置的属性。访问描述符对象由属性和设置属性和可写的价值所取代。而写,枚举,和可配置的是布尔值,当然,获取属性和设置属性的函数值。叫Object.getOwnPropertyDescriptor(),一个特定的属性描述符可以获得一个对象的ic属性:


从函数的名称,我们可以看到,Object.getOwnPropertyDescriptor()只能得到自己的属性描述符,它将返回未定义继承的属性和存在属性。要继承的财产,你需要遍历原型链(不穿越原型链别担心,下面会说的。

如果你想设置的属性的属性,或想新的属性有一些特性,你需要打电话给object.definepeoperty()导入需要修改的对象被创建或修改的属性的名称和属性描述符对象。



你可以看到:

(1)的输入object.defineproperty属性描述符对象()没有包含所有4个特点;

书写能力控制属性值的修改。

计数控制是否可枚举属性(列举属性,下同);

配置控制其他特征的修改,包括是否曾表示属性可以被删除。

如果你想修改或同时创建多个属性,你需要使用object.defineproperties()。第一个参数是要修改的对象。第二个参数是一个映射表,它包含要新建或修改的属性的名称,以及它们的属性描述符,例如:


var p = object.defineproperties({ },{
X:{价值:1、可写的:真的,真的,真的可枚举:可配置:},
Y:{价值:2、可写的:真的,真的,真的可枚举:可配置:},
R:{:函数(){ return 88;},设置:功能(价值){,x =价值;},可枚举:真的,可配置:配置:,
问:{值:函数(){ console.log(你好,世界');},可写的:真的,真的,真的可枚举:可配置:}
});



我相信你也从这个例子中看到,Object.defineProperty()和()object.defineproperties返回修改的对象。

我们之前说的getter和setter的访问性能,我们使用对象直接量语法定义新对象的访问性能,但我们不能查询属性的getter和setter方法,或添加新的访问属性的现有对象。ECMAscript 5中,你可以通过Object.getOwnPropertyDescriptor()和()object.defineproperty。但在ECMAscript 5,大多数浏览器(IE除外)都支持get和set对象直接的语法写的。所以这些浏览器也提供非用于查询和设置getter和setter标准旧的API。这些API是由4种方法,所有的对象都有这些方法。__lookupgetter__()和()是用来__lookupsetter__返回一个指定的getter和setter属性方法。__definegetter__ __definesetter__()和()是用来定义getter和setter,这四个方法是用两个强调两强调前缀是后缀来表明他们是非的标准方法。以下是他们的使用:


七。属性提取

Javascript对象可以被视为一组属性。然后我们有时需要确定一个对象中是否存在一个属性,它是下一个检测属性。

还有三种方法来检测对象的属性。这里详细描述了他们的角色和差异。

1.in算子

内运算符是左边的属性名称(字符串)和右边的对象。如果对象自身属性或继承属性的属性包含此属性,则返回true,否则返回false。

为了测试,我们首先给出一个可枚举对象添加一个object.prototype M属性,不可枚举属性N;然后,对对象的定义X两可枚举属性,y不可枚举属性,和obj对象由直接宾语形式创造,继承object.prototype.the下面的例子:


从运行结果中可以看到,内部运算符的左边是属性名(String),右边是对象。如果对象的属性或继承属性(是否可以枚举这些属性)返回false,则返回true。

2.hasownproperty()

对象的hasownproperty()方法被用于检测是否一个给定的名称是一个对象的属性(无论是列举的这些属性)。对于继承的属性,它将返回false:


3.propertyisenumerable()

propertyisenumerable()是一个增强版本的hasownproperty(),它返回到真的只有性能检测和属性列为真。或实例:


八。枚举属性

我们使用枚举属性比检测属性更常用。枚举属性,我们通常使用for循环,它可以遍历循环体中的所有枚举属性和继承属性,将属性名分配给循环变量:


我原本以为 /环与在运营商的一大的关系,现在看来,规则是不同的。当然,如果你不想通过继承的属性,然后添加一层hasownproperty()在 /循环判断:


(道具为OBJ){
如果(obj.hasownproperty(道具)){
console.log(道具);
}
}



除了为 /环,ECMAscript 5标准定义了两个函数,可以枚举的属性名称:

Object.getOwnpropertyNames(),它返回的对象的所有属性的名称,是否可以列举或不;

Object.keys(),它返回的对象的可枚举属性的名称;

或者一个例子:


九。对象的三个特殊属性

每个对象都有一个原型、一个类(类)和一个与它相关的可扩展属性。这三个是对象的特殊属性(它们只是对象的属性,并不是想象中的复杂)。

1。原型属性

如前所述,一个对象的原型属性用于继承属性(在某点上…)这个属性非常重要,我们通常直接调用O的原型属性O。原型属性是在实例创建的开始设置的。也就是说,这个属性的值是由Javascript自动设置的,然后我们将说明如何手动设置它的值。

(1)通过直接创建的对象的对象作为原型采用object.prototype。

(2)新+构造函数创建的对象使用构造函数的原型属性作为原型;

通过object.create()使用第一个参数创建对象(如果该参数为null,那么原始对象的属性值是不确定的;如果该参数是不确定的,那么一个错误:Uncaught TypeError:对象的原型可能是一个对象或无效:未定义)为原型;

那么,如何查询对象的原型属性呢在ECMAscript 5,对象被传递到object.getprototypeof()作为参数,并可以查询其原型,例如:


但在ECMAscript 3,没有Object.getPrototypeOf()函数,但obj.constructor.prototype经常用于检测物体的原型,因为每个对象都有一个构造函数属性表示对象的构造函数。

(1)对象的直接对象创建的对象的构造函数属性指向构造函数对象();

(2)新+构造函数创建的对象的构造函数属性指向构造函数;

(3) the constructor attribute of the object created by Object.create () points to the same constructor attribute as its prototype object;

检测一个对象是否是另一个对象的原型(或在原型链),该isprototypeof()方法可以使用,例如:


也有非标准但许多浏览器已经实现了一个属性__proto__。这两个下划线的开头和结尾相同,表明它是非标准的。它直接用于查询和建立对象原型。

2。属性的类型

阶级属性(阶级属性)一个对象是一个字符串,表示对象的类型信息,ECMAscript 3和ECMAscript 5不设置此属性提供了一种方式,只有一个间接的方式来查询它的toString()方法。默认(从对象。原型继承)返回这种格式的字符串对象类:{ }。因此,如果我们想得到一个对象的类,我们可以调用toString()方法的对象提取第八和第二相互位置之间的字符。然而,许多对象继承的toString()方法的重写(例如:数组、日期等),以恰当的调用toString()版本,我们必须间接调用的function.call()方法。下面的代码可以回来RN到传递给它的任何对象的类:


功能类(obj){
如果(o = NULL){
return'null;
}
如果(o =未定义){
return'undefined;
}
返回object.prototype.tostring.call(O),切片(8 - 1);
}




这类()函数可以通过任何类型的参数。下面是一个使用实例:



摘要:从结果来看,你可以看到,在三种方法创建的对象的类的属性all'object。

三.可扩展性

对象的可扩展性是用来指示一个新的属性可以被添加到对象。所有的内置对象和自定义对象是可扩展的(除非他们转换到非扩展),以及宿主对象的可扩展性是通过Javascript engine.ecmascript 5定义定义了一个函数用于查询和设置对象的可扩展性:

(查询)确定对象是否是通过对象为object.isextensible扩展()。

(设置)如果你想把一个对象的不可扩展,你需要打电话给object.preventextensions()和转移的对象作为参数传递。小心 uff1a

一旦对象转换为不可扩展对象,A就不能再转换为可扩展对象。

B.preventExtensions()只影响对象本身的可扩展性。如果将属性添加到非扩展对象的原型中,则该非扩展对象将继承这些新属性。

此外,Object.seal()和()object.preventextensions相似。除了设置对象为非膨胀性,他们也可以设置自己的对象的属性为一个inconfigurable之一。对于那些已经封闭(密封)的对象不能unsealed.object.issealed()可以用来检测对象是否是封闭的。

此外,Object.freeze()将锁定对象进行更严格的冷冻(冷冻)。除了设置一个对象不可扩展属性集是不可配置的,也可以自己所有的数据为只读(如果该对象的访问属性setter方法,访问器的属性将不会的影响,仍将值分配给他们打电话的性能),Use Object.isFrozen()来检测对象是否是总结。

摘要:Object.preventExtensions()、Object.seal()和Object.freeze()返回所有传入的对象,也就是说,他们可以被称为嵌套。

var obj = object.seal(object.create(Object.freeze({ 1 },{ x)Y:{价值:2、可写:true}));

在这句话中,我们使用object.create()函数输入的两个参数,即,第一个参数是对象创建的原型对象,第二个参数是创建属性直接定义的对象和属性的属性定义它。

十。对象的序列化

在对象的前面,对象的属性和对象属性的属性,事物还是相当多的,不知道你是否已经晕了!

对象的序列化(序列化)意味着一个对象的状态转换成一个字符串,或一个字符串可以减少到一个object.ecmascript 5提供了内置的功能json.stringify()和JSON.parse()用于序列化和恢复对象。这些方法都使用JSON作为数据交换格式。JSON的全称是Javascript对象标记——Javascript对象表示。它的语法和Javascript对象非常类似于数组的直接语法。


其中,最终jsonobj是对象的深层副本

JSON的语法是Javascript的一个子集,它不在Javascript中代表所有的价值观。支持对象,数组,字符串,无限大的数字,真的,假的,空的,他们可以被序列化和恢复。小心 uff1a

(1)南、无穷和无穷级数的结果是空的;

(2)json.stringify()只可序列化对象的枚举属性;

(3)对约会的对象序列化结果是ISO格式的日期字符串(指date.tojson()函数),但JSON.parse()仍保持其字符串的形态,但不能恢复他们原来的约会对象。

(4)函数,正则表达式,错误的对象和未定义的值不能被序列化和恢复;

以上是本文的全部内容,希望能对大家有所帮助。