JS对象详解
js的对象是什么?js的对象类型有哪些?具体实例是什么?
一、ECMA-262对JS对象的定义:
属性的无序集合,每个属性存放一个原始值、对象或函数;
对象是无特定顺序的值的数组;
对象是一种特殊的数据类型,可以包含多个成员。
对象成员:Property、Method。(Object=Property+Method)
属性(Property):对象名、属性名。封装对象的数据,表示与对象有关的值;
方法(Method):对象名、方法名。封装对象的行为,表示对象可以执行的行为或可以完成的功能;
二、JS的对象类型:
1. 内部对象:原生对象/内置对象
1)原生对象,ECMAScript提供的需要实例化(new)才能使用的对象
Object对象、Function对象、Array 对象、Boolean 对象、Date 对象、Number 对象、String对象、RegExp 对象、运算符、Error、Set对象、Map对象、Proxy 对象
原生对象常用方法:
①、Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
②、Object.create() 方法用于创建一个新对象。被创建的对象会继承另一个对象的原型,在创建新对象时还可以指定一些属性。
③、Object.defineProperties() 直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
④、Object.keys() 遍历对象,返回一个数组,包含了该对象自身的所有可枚举属性名
⑤、Object.getOwnPropertyNames() 遍历对象,返回一个数组,包含了该对象自身的可枚举和不可枚举属性名
⑥、Object.is() 方法用于判断两个值是否是相同的值
⑦、Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用
for...in循环遍历该对象时返回的顺序一致
⑧、Object.freeze()
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。
此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
2)内置对象,ECMAScript提供的不需要实例化就能使用的对象
Global (全局对象)和 Math对象
2. 宿主对象
宿主对象就是执行JS脚本的环境提供的对象,是浏览器提供的对象,用于完善ECMAScript 执行环境。早期存在较⼤的兼容性问题,当前其中⼀些主要的对象已经被⼤部分浏览器兼容,具体分为如下两⼤类:
1)BOM对象(Browser Object Model)
Window、Navigator、Screen、History、Location
2)DOM对象(Document Object Model)
Document、Anchor、Area、Base、Body、Button、Canvas、Event、Frame、Frameset、IFrame、Image、Link、Meta、Style、Form、Input Button、Input CheckBox、Input File、Input Hidden、Input Password、Input Radio、Input Reset、Input Submit、Input Text、Option、Select、Textare、Table、TableCell、TableRow
3. 自定对象
开发人员自己定义的对象。自定义对象的方法如下:
(1)对象字面量方式(通过JSON来创建对象)
var obj1 = {};var obj2 = {x:0,y:0};var obj3 = {name:‘Mary’,age:18}
缺点:使用同一个接口创建很多对象,会产生大量的重复代码。
(2)工厂模式。
function createPerson(name,age,actor){
var person = new Object();
person.name = "rose";
person.age = 18;
person.job = "actor";
person.sayName = function () {
console.log(this.name);
};
return person
}
console.log(p1 instanceof Object);//true
console.log(p1 instanceof createPerson);//false
①工厂模式就是将创建对象的语句放在一个函数里,通过传入参数来创建特定对象,最后返回创建的对象。
函数createPerson()能够根据接受到的参数来构建一个包含所有必要信息的Person对象。
可以无数次的调用这个函数,而每次它都会返回一个包含2个属性和一个方法的对象。
②缺点:工厂模式虽然可以创建多个相似的对象,但却不能解决对象标识的问题,即怎样知道一个对象的类型。
(3)创建一个 Object 实例
var person = new Object();
person.name = "rose";
person.age = 18;
person.job = "actor";
person.sayName = function () {
console.log(this.name);
};
console.log(person);
(4)构造函数模式
var obj1 = new Array;var obj2 = new Date();
①缺点:使用构造函数的主要问题是:每个方法都要在每个实例上创建一遍。
②在ECMAScript中,函数即对象,因此每定义一个函数,也就是实例化了一个对象。
③也就是说通过构造函数实例化的多个对象的方法,是多个不同的方法,但它们内部的代码以及实现的功能是相同的,这就造成了一定的资源浪费。
(5)原型模式
function Student() {}
Person.prototype.name = "rose";
Person.prototype.age = 18;
Person.prototype.sayName = function () {
console.log(this.name);
};
var p = new Student();
console.log(p);
①js中,每个函数都有一个prototype属性,它是一个指针,指向一个对象,叫做原型对象。
②使用原型模式可以让所有的实例共享原型对象中的属性和方法,也就是说,不必再构造函数中定义对象实例的信息。
③缺点:省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值。
原型模式的最大问题是由共享的本性所导致的。原型中所有属性是被很多实例共享的
这种共享对于函数非常合适。对于包含引用类型的属性来说,问题就比较突出了。因此,很少单独使用原型模式。
(6)组合使用构造函数模式和原型模式
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name);
};
var p = new Person("rose", 18);
console.log(p);
①组合使用构造函数模式和原型模式,是创建自定义类型的最常见方式。对象在引用其属性的时候,会按照原型链去查找,直到查找到Object的原型。
②构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
③结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度的节省了内存。
(7)其他模式
①动态原型模式:仅在第一次调用构造函数时,将方法赋给原型对象的相应属性,其他示例的处理方式同构造函数模式
②寄生构造函数模式:仅仅封装创建对象的代码,然后再返回新创建的对象,仍使用new操作符调用
③稳妥构造函数模式:没有公共属性,只有私有变量和方法,以及一些get/set方法,用以处理私有变量。