JavaScript对象--学习总结3

来源:互联网 发布:java输出1到100的素数 编辑:程序博客网 时间:2024/06/04 20:13

学习内容摘自 阮一峰博客

目录

  1. 概述
    1.1生成方法
    1.2键名
    1.3属性
    1.4对象的引用
    1.5表达式还是语句
  2. 属性的操作
    2.1读取属性
    2.2检查变量是否声明
    2.3属性的赋值
    2.4查看所有属性
    2.5delete命令
    2.6in运算符
    2.7for..in循环
  3. with语句

1概述

1.1生成方法

对象是javascript核心概念,也是最重要数据类型,javascrit所有数据都可以被视为对象
简单说,所谓对象,就是一种无序集合,由键值对构成key-value

var o = {    p:'hello world',    m:function(){...},    n:'heheda'};p是键名   hello world是value,之间用:冒号分割,属性(属性)与方法(属性)之间用逗号隔开

对象的三种生成方法:

  1. 直接使用大括号生成{}
  2. new Object()形式生成
  3. Object.create(null)方式生成;
    var o1 = {};var o2 = new Object();var o3 = Object.create(null);

一般来说第一种大括号简洁,第二宗写法比较清晰,第三种写法一般用在需要对象继承的场合.

1.2键名

对象的所有键名都是字符串,所以加不加引号都可以

var o = {    'p':'hello world'};//如果键名是数值,会被自动转为字符串var o ={    1:'a',    2.2:'b',    1e2:true};但是呢,以上有些标识名是不符合规范的,所以要加上单引号另外:其实单引号或者双引号,javascript都是支持的,只是说html css等都是双引号,所以javascript则一律用单引号,养成一个比较好的编程习惯而已

1.3属性

对象的每一个键名又称为属性property,如果属性的值为函数,则称为方法

var m = {    p:123,    n:function(){...}};属性或方法最后一个逗号可加可不加 都不会报错

属性可以动态创建,不用一开始就指定,这个比java里面的类创建条件可宽松自由多了….

var o1 = {};o1.m = 'haha';o1.n = function(){...};

1.4对象的引用
如果不同的变量名指向同一个对象,那么他们都是这个对象的引用,也就是说指向同一个内存地址,修改其中一个变量,会影响到其他所有变量

var o1 = {};var o2 = o1;o1.a = 1;console.log(o2.a);//1o2.a = 3;console.log(o1.a);//3o2.m = 4;console.log(o1.m);//4

上面代码中,o1和o2指向同一个对象,因此为其中给任何一个变量添加属性,另一变量都可以读写该属性,
此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量

var o1 = {};var o2 = o1;o1 = 1;console.log(o2);//{}上面代码中,o1和o2指向同一个对象,然后o1的值变为1,这时不会对o2产生影响,o2还是指向原来那个对象其实这个java还是很不一样的,java中如果地址引用,那么是链路式的,只会跟着上一个对象走,但javascript不是的,它是直接获取到了对象地址,从中间人o1获取到数据之后,就不会和中间人之间有关系了,只是说目前共同引用了一个地址而已.------var x = 1;var y = x;x = 2;console.log(y);//1很显然的结果,由于原始类型的数据时传值,所以当你获得值之后,和你的上一个变量就没半毛钱关系了.

1.5表达式还是语句

对象采用大括号表示,这导致了一个问题:如果行首是一个大括号,他到底是表达式还是语句?

{foo:300}

为了避免这种奇异,javascript规定.如果首行是大括号一律解释为语句即代码块,如果要解释为表达式,必须在大括号前加上圆括号.
这种差异在eval中反应的非常明显

eval('{foo:123}');//123eval('({foo:123})');//{foo:123}

上面代码中,如果没有圆括号,将其理解为代码块,加上圆括号,就理解成一个对象
var o = {
p:’hello world’
};
o.p;//hello world
o[‘p’];//hello world
注意,如果使用方括号运算符,键名必须放在引号里面,否则会被当做变量处理,但是,数字键可以不加引号,因为会被当做字符串处理

var p = {    0.4:'hello world'};o['0.4']; //hello wroldo[0.4];//hello world------方括号运算符内部可以使用表达式o['hello'+'world'];o[3+3];//数字键名不能使用点运算符(因为会被当小数点),只能使用方括号运算符

2.2检查变量是声明

如果读取一个不存在的键,会返回undefined,而不是报错,可以利用这一点,来检查一个全局变量是否被声明.

//检查a变量是否被声明if(a){...}//报错if(window.a){...}//不报错//node中if(globa.a){...}if(window['a']){...}//不报错

上面的后两种写法之所以不报错,是因为浏览器环境,所有全局变量都是window对象的舒心g,window.a的含义就是读取window对象的a属性,如果该属性不存在,就返回undefined,并不会报错.
但是,后两种有个缺点,就是a可能值为false,0或者null
那么这样判断是不合理的,更好的方式是

if('a' in window){    //变量声明过}else{    //变量未声明过}

2.3属性的赋值

点和方括号运算符不仅可以读取对象的值,还可赋值
javascript允许属性的后绑定,也就是说,你可以在任意时刻新增属性,没必要在定义对象的时候,就定义好属性
示例:

o.p = 'abc';o['p'] = 'abc;------var o = {};o.p = 1

2.4查看所有属性

查看一个对象本身所有的属性,可以使用Object.keys方法

var o = {    key1:1,    key2:2};Object.keys(o);//['key1','key2'];

2.5delete命令

delete命令用于删除对象的属性,删除成功后返回true.

var o = {p:1};Object.keys(o);//["p"]delete o.p //trueo.p//undefinedObject.keys(o)//[]

上面代码,delete命令删除了o对象的p属性,删除后,再读取p属性就会返回undefined,而且Object.keys方法的返回值中,o对象也不再包括该属性.
注意,delete即使所删除的对象属性,不存在,delete也不会报错而且返回true

var o = {};delete o.p;

因此不能根据delete来确定某属性是存在的,只能确定该属性为undefined.
只有一种情况,delete命令会返回false,那就是该属性存在,且不得删除

var o = Object.defineProperty({},'p',{    value:23,    configurable:false});o.p//123delete o.p//false

delete只能删除对象本身的属性,无法删除继承的属性.

var o = {};delete o.toString //trueo.toString //function toString(){[native code]}

上面代码中,toString是对象o继承的属性,虽然delete命令返回true,该属性并没有被删除,毅然存在.
最后,delete命令不能删除var 命令声明的变量,只能用来删除对象属性.

var p = 1;delete p//falsedelete window.p//false

上面命令中,p是var命令声明的变量,delete命令无法删除它,返回false.因为var声明的全局变量都是顶层对象的属性而且默认不得删除

2.6in运算符

in运算符用于检查对象是否包含某个属性,如果包含就返回true否则返回false

var o = {p:1};'p' in o;//true

在javascript语言中,所有全局变量都是顶层对象(浏览器的顶层对象就是window对象)的属性,因此可以用in运算符判断,一个全局变量是否存在.

//假设变量x未定义//写法一:报错if(x){return 1;}//写法二:不正确if(window.x){return 1;}//如果x设置为null或者0或者false的时候检查不出来//写法三:正确if('x' in window){return 1;}

in运算符的一个问题是,它不能识别对象继承的属性

var o = new Object();o.hasOwnProperty('toString');//false'toString' in o;//true

上面代码中,toString方法不是对象o,自身的属性,而是继承的属性,hasOwnProperty方法可以说明这一点.但是,in运算符不能识别,对继承的属性也返回true.

for…in循环

var o = {a:1,b:2,c:3};for(var i in o){    console.log(o[i]);}

下面是一个使用for…in循环,提取对象属性的例子

var obj = {    x:1,    y:2};var props = [];var i = 0;for(props[i++] in obj);console.log(props);

for…in循环有两个使用注意点.

它遍历的是对象所有可便利(enumerable)的属性,会跳过不可遍历的属性
它不仅遍历对象自身的属性,还遍历继承的属性.
请看下面的例子.

//name是person本身的属性function Person(name){    this.name = name;}//describe是Person.prototype的属性Person.prototype.describe = function(){    return 'Name: '+this.name;};var person = new Person('jane');//for...in循环会遍历实例自身的属性(name)//以及继承的属性(describe)for(var key in person){    console.log(key);}//name//describe

如果只遍历对象本身的属性,可以再加一个判断

for(var key in person){    if(person.hasOwnProperty(key)){        console.log(key);    }}//nameperson.toString()//[object object]

这个toString属性不会被for…in循环遍历到,因为他默认设置为不可遍历
一般情况下,都只是想遍历对象自身的属性,所以不推荐使用for…in循环

3with语句

with语句的格式如下

with(object){    statements;}//他的作用是操作统一个对象的多个属性时,提供一些书写方便with(o){    p1 = 1;    p2 = 2;}//等同于o.p1 = 1;o.p2 = 2;//例2with(document.link[0]){    console.log(href);    console.log(title);    console.log(style);}//等同于console.log(document.links[0].href);console.log(document.links[0].title);console.log(document.links[0].style);

注意,with区块内部的变量,必须是房钱对象已经存在的属性,否则会创造一个当前作用于的全局变量,这是因为with区块没有改变作用域,它的内部毅然是当前作用域,素以不要使用with…

0 0
原创粉丝点击