JavaScript || 对象

对象

对象是JavaScript的基础数据范例:属性的无序鸠合。每一个属性key: value和属性形貌符descripter构成。

  • 属性名key:字符串或正当的变量标识符;

  • 属性值value:可所以恣意JavaScript值(numberstringbooleannullundefined和数组、对象).
    value可所以gettersetter

  • 属性形貌符descripter:每一个属性的三个相干特征writableenumerableconfigurable,其值都是布尔范例,默许都为true

1 建立对象

建立对象有三种要领:对象字面量{a: 1}new Constructor()Object.create()

1.1 对象字面量

var book = {
    "main title": "JavaScript",                   //有空格或其他非标识符、关键字,必需运用双引号
    "sub-title": "The Definitive Guide",
    "for": "all audiences",
    author: {
        firstname: "David",
        lastname: "Flanagan"
    }
}

1.2 new操纵符挪用组织函数

能够运用new操纵符挪用一个组织器函数Constructor()建立一个对象。

var o = new String();
var d = new Date();

1.3 Object.create()要领

原型:每一个JS对象都有一个与之相干联的原型对象prototype,对象其原型对象上继续属性。(当前对象中的__proto__属性是其原型对象的链接)

一切经由历程字面量建立的对象的原型都是Object.prototype,一个字面量对象{}相当于挪用new Object()

Object.prototype的原型是null,所以null是原型的出口。

Object.create()是一个静态函数(不是供应给对象挪用的要领),用于建立对象:

  • 第一个参数:原型对象,建立的新对象以该参数为原型;

  • 第二个参数:可选,用于对对象属性的形貌

  • 建立一个没有原型的对象:Object.create(null);

  • 建立一个一般空对象({}new Object()):Object.create(Object.prototype);

2 对象三个特别属性

每一个对象都有与之相干的3个属性:原型prototype、类属性calss attribute、可扩大性extensible attribute

2.1 原型

每一个JS对象都与另一个原型对象(prototype),应用原型能够完成继续。

  • 字面量的原型是:Object.prototype

  • new操纵符建立的对象其原型:组织器函数的原型(prototype属性)

  • Object.create()建立的对象,其原型:第一个参数

查询对象的原型

  • ES5中定义了Object.getPrototypeOf()函数,来查询对象的原型

  • 应用new建立的对象会继续constructor属性,指向建立该对的组织器函数,一切该对象的原型是:obj.constructor.prototype

  • 字面量{}constructor属性指向Object()

  • 运用isPrototypeOf()要领检察一个对象是不是为另一个对象的原型(或处于原型链中)

    Array.prototype.isPrototypeOf([]);   //  ==> true

2.2 类属性

对象的类属性class attribute是一个字符串,用来示意对象的信息。ES3与ES5均为供应设置类属性的API,只能经由历程继续自Object.prototypetoString()要领来简约查询。

{}.toString();    //  ==> "[object Object]"

经由历程对返回字符串切片:第8位到倒数第2位即可取得对象的范例。然则很多对象重写了toString()要领,须要间接挪用Functioncall()要领

function classof(o) {
    if(o === null) {return "Null";}
    if(o === undefined) {return "Undefined"}
    return Object.prototype.toString.call(o).slice(8, -1);
}

classof()要领能够返回通报给它的恣意对象的范例,参数为numberstringboolean时,运用包装范例将其转化为对象,再举行操纵。

    classof(null);  // ==> "Null"
    classof(2);  // ==> "Number"
    classof(false);  // ==> "Boolean"
    classof(new Date());  // ==> "Date"
    classof("");  // ==> "String"
    classof({});  // ==> "Object"
    classof([]);  // ==> "Array"
    classof(/./);  // ==> "RegExp"
    classof(window);  // ==> "Window",宿主对象
    function F() {};    //自定义一个组织器函数
    classof(new F());  // ==> "Object"

2.3 可扩大性extensible attribute

对象的课扩大性用来形貌对象是不是能够增添新的属性。一切的内置对象和自定义对象都是可扩大的,除非将其转化为不可扩大

  • Object.esExtensible()函数推断传入对象是不是能够扩大;

  • Object.preventExensible()函数将传入的对象设置为不可扩大,而且历程不可逆;只影响对象本身的可扩大性

  • Object.seal()函数将对象设置为不可扩大,属性形貌符configurable设置为false(不能增添新属性,已有的属性不能删除或设置,然则关于writable: true时,能够修正属性的值);历程不可逆

  • Object.isSealed()函数推断一个对象是不是关闭

  • Object.freeze()函数将对象设置为不可扩大,属性形貌符configurable: false;writable: false;只读。valueaccessor property含有setter函数,不受影响

3 构成对象的属性

每一个对象是无需的属性鸠合,属性名可所以正当的变量标识符或字符串;变量值可所以恣意JavaScript值;属性由形貌符descripter来掌握特征;

3.1 属性的查询与设置

属性能够经由历程.[]来接见:

  • 运用.接见时,其右边必需是属性称号定名的简朴标识符

  • 运用[]接见时,括号内必需是计算结果为字符串的表达式,字符串是属性的名字。变量名为关键字、含有空格或属性名是变量时,必需运用[]

    var author = book.author;
    var name = author.surname;
    var title = book["main title"];

属性的设置:与接见类似,将其放在赋值表达式的左边

    book.edtion = 6;
    book["main title"] = "ECMAScript";

继续与毛病

在查询一个对象是不是存在时,先检察本身属性,假如没有;经由历程原型链逐层向上查找,直到原型链顶端null为止。

  • 假如本身属性与原型链中均为找到,属性接见返回undefined,不报错

  • 假如查询不存在对象的属性,会报错

  • nullundefined设置属性会报错

3.2 属性删除

运用delete操纵符,能够删除对象的属性(其形貌符中configurabletrue),而且只能删除自有属性,不能删除继续属性

3.3 属性检测

推断某个属性是不是在某个对象中,JS有三种要领:inhasOwnProperty()propertyIsEnumerable()

  • in:假如对象本身属性或继续属性中包含该属性,返回true;

  • hasOwnProperty():只要对象本身属性包含该属性时,才返回true

  • propertyIsEnumerable():只要对象本身属性包含该属性,而且该属性是能够罗列(形貌符中enumerable: true;

    var o = {a : 1};
    "a" in o;  //  ==> true
    o.hasOwnProperty("a");  //  ==> true
    o.propertyIsEnumerable("a");  //  ==> true

3.4 罗列属性

运用for-in轮回能够遍历对象中一切可罗列的属性(包含本身属性与继续属性),把属性名赋值给轮回变量。ES5定义了Object.keys()Object.getOwnPropertyNames()两个函数用来罗列属性称号。

  • Object.keys():返回对象中可罗列的自有属性名构成的数组

  • Object.getOwnPropertyNames():返回对象一切的自有属性名构成的数组,包含不可罗列的属性

对象继续的内置要领都是不可罗列的,给对象中增添的属性都能够罗列(除非设置其enumerable: false

有很多运用东西库为Object.prototype增添新的属性,这些属性能够被一切对象继续运用,然则在ES5之前,不能将其设置为不可罗列,所以在for-in轮回时会被罗列出来。

//过滤继续的属性
for(p in o) {
    if(!o.hasOwnProperty(p)) {continue;}
}
//跳过要领
for(p in o) {
    if(typeof p === "function") {continue;}
}

操纵对象属性的东西函数:

/**
 * 罗列属性的东西函数
 * 将对象p中可罗列的属性复制到对象o中,返回对象o;
 * 假如p和o含有同名的属性,则掩盖o中的属性
 * 不处置惩罚getter和setter以及复制属性
 */
function extend(o, p) {
  for(let prop in p) {
    o[prop] = p[prop];
  }
  return o;
}

/**
 * 将对象p中可罗列的属性复制到对象o中,返回对象o;
 * 假如o和p有同名属性,不影响o中的属性
 * 不处置惩罚getter和setter以及复制属性
 */
function merge(o, p) {
  for(let prop in p) {
    if(o.hasOwnProperty(prop)) {
      continue;
    }
    o[prop] = p[prop];
  }
  return o;
}

/**
 * 假如o中的属性在p中没有同名属性,从o中删除这个属性,并返回o
 */
function restrict(o, p) {
  for(let prop in o) {
    if(!(prop in p)) {
      delete o[prop];
    }
  }
  return o;
}

/**
 * 假如o中的属性在p中存在同名属性,从o中删除这个属性,并返回o
 */
function substrict(o, p) {
  for(let prop in o) {
    if(prop in p) {
      delete o[prop];
    }
  }
  return o;
}

/**
 * 返回一个数组,包含o中可罗列的自有属性的名字
 */
function keys(o) {
  //o必需是对象
  if(typeof o !== 'object') {
    throw TypeError();
  }
  var result = [];
  for(let prop in o) {
    if(o.hasOwnProperty(prop)) {
      result.push(prop);
    }
  }
  return result;
}

3.5 属性settergetter

属性的构成:keyvaluedescripter。在ES5中,value能够用一个或两个要领替换(gettersetter要领)

  • 一切JavaScript的value叫做数据属性data property

  • gettersetter定义的属性叫做存取器属性:accessor property

不同于data propertyaccessor property的读写属性由gettersetter决议。

  • 假如属性同时有gettersetter,它是一个可读写的属性;

  • 假如属性只要getter,它是一个只读的属性;

  • 假如属性只要setter,它是一个只写的属性;读取只写属性老是返回undefined

gettersetter定义

var o = {
    data_prop: value;        //一般数据属性
    
    //存取器属性是成对定义的函数,函数名是该属性名,没有冒号分开函数体以属性名
    get accessor_prop() {...},
    set accessor_prop(value) {...}
}
var p = {
  //x、y是一般可读写的数据属性
  x: 1.0,
  y: 1.0,

  //r是可读写的存取器属性,具有getter和setter
  //函数完毕后要带上逗号
  get r() {return Math.sqrt(this.x * this.x + this.y * this.y)},
  set r(newvalue) {
    var oldvalue = Math.sqrt(this.x * this.x + this.y * this.y);
    var ratio = newvalue / oldvalue;
    this.x *= ratio;
    this.y *= ratio;
  },
  //theta是只读存取器属性,只要getter要领
  get theta() {return Math.atan2(this.y, this.x)}
};
  • 函数体内的this指向示意这个点的对象

3.6 属性的形貌符descripter

属性除keyvalue,另有一组用于形貌其特征的descripter,其中有writableenumerableconfigurable三个属性,其值都为布尔范例,默许为true

假定将settergetter看作descripter,同理将属性的value也看作descripter

  • data property的四个特征:valuewritableenumerableconfigurable

  • accessory property的四个特征:gettersetterenumerableconfigurable

ES5供应操纵descripter的API:

  • 挪用Object.getOwnPropertyDescripter()函数,猎取某个对象中特定自有属性的descirpter

  • 挪用Object.getPrototypeOf()函数能够猎取继续属性的descirpter

  • 挪用Object.defineProperty()函数能够设置属性的特征,或许新建属性,使其具有某种特征

    //返回{ value: 1, writable: true, enumerable: true, configurable: true }
    Object.getOwnPropertyDescriptor({a: 1}, "a");
    
    //继续属性和不存在的属性,返回undefined
    Object.getOwnPropertyDescriptor({});
    Object.getOwnPropertyDescriptor({}, "toString");
    var o = {};   //建立空对象
    //增添一个不可罗列的属性,其值为1
    Object.defineProperty(o, "x", {value: 1, writable: true, enumerable: false, configurable: true});
    
    o.x;  //属性存在,但不可罗列, ==>1
    Object.keys(o);     //  ==>  []
    
    //对x属性举行修正,使其变成只读
    Object.defineProperty(o, 'x', {writable: false});
    
    o.x = 2;     //操纵失利,但不报错;在严厉形式下抛出范例毛病
    o.x;    //  ==> 1
    
    //属性的值能够设置
    Object.defineProperty(o, 'x', {value: 2});
    o.x;    //  ==> 2
    
    //将x从数据属性修正为存取器属性
    Object.defineProperty(o, 'x', {get function() {return 0;}});
    o.x;   //==> 0

4 序列化对象

序列化对象指将对象的状况转化为字符串,同时能够将JSON字符串转化为对象。ES5内置JSON对象的JSON.stringgify()JSON.parse()能够完成序列化和剖析。

var o = {x: 1, y: {z: [false, null, ""]}};   //测试对象
var s =JSON.stringify(o);         //  '{"x":1,"y":{"z":[false,null,""]}}'
var p = JSON.parse(s);         //p是s的深拷贝

JSON是JavaScript的子集,不能示意JavaScript中一切值。

  • 能够示意:objectArraystringnumberbooleannull,能够序列化与复原。infinityNaN序列化结果是nullDate对象序列化结果是日期字符串

  • 不能示意:函数、RegExpError对象和undefined

  • JSON.stringify()只能序列化对象自有的可罗列属性。

5 Object.prototype对象的要领

  • hasOwnProperty():检测该属性是不是为对象自有属性

  • propertyIsEnumerable():检测该属性是不是是对象自有,而且可罗列的属性

  • isPrototypeOf:检测某对象是不是为另一个对象的原型

  • toString():无参数,返回挪用该要领对象值的字符串,因为功用有限,某些对象重写了该要领:Array.toString()Date.toString()Function.toString()

  • toLoaclString()Object中的toLoaclString()只是挪用toString(),只要DateNumber类对toLoaclString()定制,能够对数字、日期和时候举行本地化处置惩罚

6 总结

  1. JS中对象是属性的无序鸠合,每一个对象有三个相干特征:原型prototype、类属性class property、可扩大性extensible

  2. 对象的建立三种要领:对象字面量、new挪用组织函数和Object.create()

  3. 每一个属性由三个部份构成:keyvaluedescripter

    • key只能是字符串或许值为字符串的变量标识符

    • value可所以恣意JavaScript值(数据属性data property);可所以一个或两个要领,gettersetter(掌握区属性accessor property

    • descripterwritableenumerableconfigurable,其值都是布尔范例,默许都为true。能够运用Object.defineProperty()操纵形貌符特征。

  4. writable指该属性是不是能够写入数据;enumerable指该属性是不是能够罗列,(运用for-in轮回能够列出,ES5供应Object.keys()Object.getOwnPropertyNames());configurable指该属性是不是能够用delete操纵符删除和设置。

    原文作者:Kyxy
    原文地址: https://segmentfault.com/a/1190000008521798
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞