JavaScript_对象

javaScript中的对象有内置对象宿主对象自定义对象
内置对象:数组,函数,日期,正则表达式;
宿主对象:javascript解析器所在的宿主,比如web浏览器,宿主环境定义的对象document,DOM对象等;
自定义对象:在js中自己创建的对象;

对象是由无序的名/值对(属性)组成;属性名可以是包括空字符串在内的任意字符串;


创建对象
有三种方式可以创建对象
1.对象字面量
2.通过new关键词来创建对象
3.通过Object.create()方法来创建对象

Object.create(prototype[,propertiesObject]);
参数
prototype:Object类型;作为新创建对象的原型对象;可以取值为null;
propertiesObject:为新创建对象绑定的属性;
返回值
返回指定原型对象上添加新属性后的对象。

例子

var o=Object.create(null);
console.info(Object.getPrototypeOf(o));//undefined;
//下面三种写法是等价的
var o=Object.create(Object.prototype);
var o={};
var o=new Object();
function Person(name){
this.name=name;
};
Person.prototype.eat = function(){
console.info("eat");
};
var p=Object.create(Person.prototype);
console.info(p.constructor);//Person;
var o=Object.create(Object.prototype,{
      name:{
        writable:true,
        value:"zhang",
        enumerable:true,
        configurable:false
      }
});
for(var i in o){
console.info(i);//name
};
//简单的实现原型继承
function inherit(p){
  if(p==null){
  throw TypeError();
  }else if(typeof p !=="object"&&typeof p !=="function"){
  throw TypeError();
  };
  if(Object.create){
    return Object.create(p);
  }else{
  function f(){};
  f.prototype=p;
  f.prototype.constructor=f;
  return new f();
  }
}
  

查询属性
可以通过(.)运算符或([])方括号来获取属性的值。对于点运算符来说,右侧必须是一个以属性名称命名的简单标识符。对于方括号来说,方括号内必须是一个计算结果为字符串或可以转换为字符串的表达式,这个字符串就是属性的名字。ES3中,点运算符后面的标识符不能是保留字,只能通过方括号来访问它们,ES5对此放宽了限制,可以在点运算符后面直接使用保留字。
方括号的形式可以动态的访问属性,或者属性名中有空格出现的情况,推荐使用。

设置属性
属性设置分为几种情况:1.如果要设置的属性是对象中不存在的(原型链和对象本身都没有),则相当于给对象创建了一个自有属性;2.如果要设置的属性在原型链中存在且writable为false,则不能设置该属性;3.如果要设置的属性是自有属性,不是继承而来的,则修改这个自有属性;4.如果要设置的属性在原型链中存在且是具有setter方法的访问器属性,那么这时将调用setter方法而不是给对象创建一个自有属性,需要注意的是setter方法是由对象来调用的,而不是定义这个属性的原型对象调用的。因此setter方法定义任意属性,这个操作只是针对对象本身,而不会修改原型链。5.如果要设置的属性在原型链中,且writable为true,则相当于为对象创建一个自有属性,覆盖了原型链上的同名属性。6.如果要设置的属性在原型链中,且为访问器属性,但是没有setter方法,则不能设置该属性。
总结:属性设置的结果包括:设置不成功;为对象创建一个属性;修改对象上原有的属性;一个例外(上述第四种情况);
规律特性:设置属性时,首先判断原型链,以此判断是否允许赋值操作;

//第一种情况
var o={};
o.x="zhang";
console.info(o);//{x: "zhang"}
//第二种情况
var p={};
Object.defineProperty(p,"x",{value:"zhang",writable:false});
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";
//第三种情况
var o={x:"zhang"};
o.x="wang";
console.info(o.x);//"wang";
//第四种情况
var p={
"age":25,
get x(){
return "zhang";
},
set x(name){
this.name=name;
}
};
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";
console.info(o.name);//"wang";setter内部创建了一个name属性
//第五种情况
var p={};
Object.defineProperty(p,"x",{value:"zhang",writable:true});
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"wang";
console.info(p.x);//"zhang";
//第六种情况
var p={
"age":25,
get x(){
return "zhang";
}
};
var o=Object.create(p);
o.x="wang";
console.info(o.x);//"zhang";

删除属性
delete操作符可以删除对象的自有属性,它的操作数应当是一个属性访问表达式。delete只是断开属性和宿主对象的联系,而不会去操作属性中的属性;

var o={p:{x:1}};
var n=o.p;
delete o.p;
console.info(n.x)//1;

由于已经删除的属性的引用依然存在,所以这种不严谨的代码会造成内存泄漏,所以在销毁的属性是对象类型的时候,要遍历属性中的属性,依次删除。

function deleteProperty(o, p) {

    function isObjectOfProperty(property) {
        return (Object.prototype.toString.call(o[property]) === "[object Object]") ? true : false;
    }

    if (arguments.length == 1 && typeof arguments[0] == "object") {
        for (var item in o) {
            isObjectOfProperty(item) ? deleteProperty(o[item]) : (delete o[item]);
        }
    } else if (arguments.length == 2 && typeof arguments[0] == "object" && typeof arguments[1] == "string") {
        isObjectOfProperty(p) ? deleteProperty(o[p]) : (delete o[p]);
    } else {
        return false;
    }
};

注意细节
1、delete只能删除自有属性,不能删除继承过来的属性;
2、delete不能删除可配置性为false的属性,可以删除不可扩展对象的可配置属性,比如prototype对象的可配置属性constructor;
3、通过变量声明和函数声明创建的全局对象的属性是不可配置的,不能用delete操作符删除;
4、在非严格模式中,删除全局对象的可配置属性时,可以省略对全局对象的引用,直接在delete操作符后跟随要删除的属性;在严格模式下则会报错;
5.delete操作符在什么情况下返回true/false;(删除不存在的属性,删除继承过来的属性,删除configuable为true的属性;这几种情况返回true)

//不能删除继承属性
var p={x:1};
var o=Object.create(p);
console.info(o.x);//1
delete o.x;//true;
console.info(o.x);//1
//不能删除configurable为false的属性
var p=Object.create(Object.prototype,{
  name:{
      value:"zhang",
      writable:true,
      enumerable:true,
      configurable:false;
 }
});
delete p.name;//false;
//在全局作用域中通过var,function创建的变量和函数声明是不可配置的,不能删除
var x=1;
function test(){};
delete this.x;//false;
delete this.test;//false;
//严格模式和非严格模式使用delete
"use strict"
var p={x:1};
delete x;//报错
delete p.x;//true;
//delete后不是一个属性访问表达式
delete 1;//true

检测属性
检测某个属性是否属于指定对象;可以使用in运算符或Object.prototype.hasOwnProperty()和Object.prototype.propertyIsEnumerable();
分以下几种情况:
1.检测的属性不区别是自有的还是继承过来的;

var o={"name":"zhang"};
"name" in o;//true;
“toString" in o;//true;

2.检测自有属性

var o={"name":"zhang"};
o.hasOwnProperty("name");//true;
o.hasOwnPropery("toString");//false;

3.检测自有属性中的可枚举属性

var o={};
Object.defineProperty(o,"name",{value:"zhang",enumerable:false});
o.age=26;
o.propertyIsEnumerable("name");//false;
o.propertyIsEnumerable("age");//true;

枚举属性
有三种方式可以枚举属性:
1.for in 循环;
2.Object.keys();
3.Object.getOwnPropertyNames();
分以下几种情况
1.枚举自有属性和继承属性(enumerable为true)

var o={x:2};
for(item in o){
//打印自有属性x,因为继承的内置对象属性都是不可枚举的
console.info(item);//x;
}

2.枚举自有属性(enumerable为True)

var o={x:2};
Object.defineProperty(o,"y",{value:3});
Object.keys(o);//["x"];

3.枚举所有的自有属性,不仅仅是可枚举的属性

var o={x:2};
Object.defineProperty(o,"y",{value:3});
Object.getOwnPropertyNames(o);// ["x", "y"]

存取器属性的setter和getter

var o={
name:"zhang",
y:26,
get age(){
return this.y;
},
set age(newV){
this.y=newV;
}
}
console.info(o.age);//26;
o.age=20;
console.info(o.y);//20;
console.info(o.age);//20;

属性特性

属性分为数据属性和存取器属性;


数据属性有四个特性:
1.value(值属性);
2.writable(可写属性);------表明是否可以设置该属性的值(控制value这个属性);
3.enumerable(可枚举属性);------表明该属性是否可以通过for...in循环返回该属性;
4.configurable(可配置属性);------表明是否可以删除或修改该属性;(控制writable,enumerable属性)

用法:writable特性控制是否可以修改value的值;configurable特性控制是否可以修改enumerable和writable特性,但是如果writable为true时,可以修改为false,反之则不可;当configurable为false时,不能修改为true;

var o={};
Object.defineProperty(o,"name",{value:"zhang",writable:false,enumerable:false,configurable:true});
console.info(o.name);//"zhang";
//当writable为false时不能修改属性的值
o.name="wang";
console.info(o.name);//"zhang";


存取器属性有四个特性:
1.get属性(读取);
2.set属性(写入);
3.enumerable(可枚举属性);------表明该属性是否可以通过for..in循环返回该属性;
4.configurable(可配置属性);------表明是否可以删除或修改该属性;

对象属性

对象本身也拥有三个特性;
1.对象的原型:指向另一个对象,本对象的属性继承自它的原型对象。
2.对象的类(class):一个标识对象类型的字符串。
3.对象的扩展标记:指明了是否可以向该对象添加新属性。

对象的原型属性是实例对象创建之初就设置好的,查询原型特性可以使用Object.getPrototypeOf();在ES3中没有与之对应的方法,通常使用表达式o.constructor.prototype来检测一个对象的原型(这种方式存在问题);要检测一个对象是否是另一个对象的原型,使用isPrototypeOf();

对象的类属性用来表示对象的类型信息,ES3,ES5都未提供设置这个属性的方法,并只有一种间接的方法可以查询它。Object.prototype.toString();
toString方法大多被重写了,所以要使用Function.call()来调用Object.prototype.toString;

var a=[];
var r=Object.prototype.toString.call(a);
console.info(r);//"[object,Array]";
r.slice(8,-1);//"Array";

对象的扩展属性用以表示是否可以给对象添加新属性,内置对象和自定义对象都是默认可扩展的。宿主对象的可扩展性由javaScript引擎定义。

判断对象是否是可扩展的
Object.isExtensible();

var o={};
Object.isExtensible(o);//true;

设置对象为不可扩展的
Object.preventExtensions()
这个方法只影响对象本身的可扩展性。如果给一个不可扩展对象的原型对象添加一个属性,对象仍然可以继承这个属性。

var o={};
Object.preventExtensions(o);
console.info(Object.isExtensible(o));//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";

密封对象(seal)
Object.seal();
Object.isSealed();
这个方法除了能够将对象设置为不可扩展的,还可以将对象的所有自有属性都设置为不可配置的。

var o={};
Object.defineProperty(o,"age",{value:26,writable:true,enumerable:true,configurable:true});
Object.seal(o);
console.info(Object.isSealed(o));//true;
console.info(Object.getOwnPropertyDescriptor(o,"age")["configurable"]);//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";

冻结对象(frozen)
Object.freeze();
Object.isFrozen();
这个方法可以将对象设置为不可扩展的,还可以将对象的所有自有属性设置为不可配置的,还可以将对象的所有数据属性设置为只读(如果对象的存取器属性具有setter方法,存取器属性不受影响,仍然可以使用属性赋值调用他们);

var o={};
Object.defineProperty(o,"age",{value:26,writable:true,enumerable:true,configurable:true});
Object.freeze(o);
console.info(Object.isFrozen(o));//true;
console.info(Object.getOwnPropertyDescriptor(o,"age")["configurable"]);//false;
console.info(Object.getOwnPropertyDescriptor(o,"age")["writable"]);//false;
var p=Object.getPrototypeOf(o);//获取o的原型对象
p["name"]="zhang";
console.info(o.name);//"zhang";

preventExtensions(),seal(),freeze()三个方法都返回一个新对象,所以可以链式的调用

//创建一个封闭对象,包括一个冻结的原型和一个不可枚举的属性
var o=Object.seal(Object.create(Object.freeze({x:1}),{y:{value:2}}));
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • 作者:clearbug原文地址:http://www.cnblogs.com/craftsman-gao/p/48...
    IT程序狮阅读 785评论 1 8
  • 对象 对象是动态的——可以新增属性也可以删除属性,但是对象经常用来模拟静态对象以及静态类型语言中的“结构体”。对象...
    Allen_HD阅读 254评论 0 1
  • 对象是一种复合值:它将很多值(原始值或其他对象)聚合在一起,可通过名字访问这些值。对象也可看做是属性的无序集合,每...
    kissLife阅读 531评论 0 2
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,525评论 0 5
  • 序 从最近的js入门系列的阅读量逐步递减,观众老爷的兴趣也不再能够接受一些细节性的地方深度挖掘,让我有了一些思考。...
    zhaolion阅读 1,574评论 5 19