神刀安全网

JS学习-对象

一 概述

对象的概念和java一样,就是一种抽象的概念,万物皆对象

1.1 生成方法

通常有三种方法

  • 直接使用大括号生成( {}

    var o = {
    p1: 'Hello',
    p2: 'World'
    };

​ 大括号就定义了一个对象,包含了两个键值对的对象,该对象被赋值给变量 o

p 是“键名”(成员的名称),字符串 Hello World 是“键值”(成员的值)

  • new 命令生成一个Object对象的实例
  • 使用 Object.create 方法生成。

    var o1 = {};
    var o2 = new Object();
    var o3 = Object.create(null);

    上面三行语句是等价的

​ 第三种写法一般用在需要对象继承的场合

1.2 键名

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

    var o = {
    'p': 'Hello World'
    };

  • 如果键名是数值,会被自动转为字符串:

    var o ={
    1: 'a',
    3.2: 'b',
    1e2: true,
    1e-2: true,
    .234: true,
    0xFF: true,
    };

    o
    // Object {
    // 1: "a",
    // 100: true,
    // 255: true,
    // 3.2: "b",
    // 0.01: true,
    // 0.234: true
    // }

  • 不合法的键名必须加上引号

  • 键名如果既不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),也不是数字,则必须加上引号,否则会报错

    var o = {
    '1p': "Hello World",
    'h w': "Hello World",
    'p+q': "Hello World"
    };

注意,JavaScript的保留字可以不加引号当作键名

1.3 属性

对象的每一个“键名”又称为“属性”(property)

  • “键值”可以是任何数据类型

    如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用

    var o = {
    p: function (x) {
    return 2 * x;
    }
    };

    o.p(1)
    // 2

  • 对象的属性之间用逗号分隔,最后一个属性后面可以加逗号(trailing comma),也可以不加

  • 属性可以动态创建,不必在对象声明时就指定

    var obj = {};
    obj.foo = 123;
    obj.foo // 123

​ 上面代码中,直接对 obj 对象的 foo 属性赋值,结果就是在运行时创建了 foo 属性。

  • name属性

    由于对象的方法就是函数,因此也有 name 属性

    var obj = {
    m1: function m1() {},
    m2: function () {}
    };

    obj.m1.name // m1
    obj.m2.name // undefined

1.4 对象的引用

和java类似

  • 指向同一个对象的不同变量指向同一个内存地址,修改其中一个变量,会影响到其他所有变量

    var o1 = {};
    var o2 = o1;

    o1.a = 1;
    o2.a // 1

    o2.b = 2;
    o1.b // 2

  • 如果取消某一个变量对于原对象的引用,不会影响到另一个变量。

    var o1 = {};
    var o2 = o1;

    o1 = 1;
    o2 // {}

​ 上面代码中, o1o2 指向同一个对象,然后 o1 的值变为1,这时不会对 o2 产生影响, o2 还是指向原来的那个对象。

  • 原始类型数据的赋值和对象引用不同,是值传递

    var x = 1;
    var y = x;

    x = 2;
    y // 1

​ 上面的代码中,当 x 的值发生变化后, y 的值并不变,这就表示 yx 并不是指向同一个内存地址。

1.5 表达式还是语句?

{ foo: 1 }

由于对象采用大括号表示,所以如果行首是一个大括号,会产生歧义

  • 这是一个表达式,表示一个包含 foo 属性的对象;
  • 这是一个语句,表示一个代码区块,里面有一个标签 foo ,指向表达式 123

为了避免这种情况,JavaScript规定,如果行首是大括号,一律解释为语句(即代码块)。如果要解释为表达式(即对象),必须在大括号前加上圆括号:

({ foo: 1})

二 属性的操作

2.1 读取属性

读取对象的属性,有两种方法

  • 使用点运算符
  • 使用方括号运算符

注意:

  • 如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。但数字键可以不加引号,因为会被当作字符串处理。

    var o = {
    p: 'Hello World'
    };

    o.p // "Hello World"
    o['p'] // "Hello World"

  • 如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。由于数字键会被当作字符串处理,可以不加引号。

    var o = {
    0.7: 'Hello World'
    };

    o['0.7'] // "Hello World"
    o[0.7] // "Hello World"

  • 方括号运算符内部可以使用表达式

    o['hello' + ' world']
    o[3 + 3]

  • 数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。

    obj.0xFF
    // SyntaxError: Unexpected token
    obj[0xFF]
    // true

2.2 检查变量是否声明

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

// 检查a变量是否被声明
if (a) {...} // 报错

if (window.a) {...} // 不报错
if (window['a']) {...} // 不报错

上面的后二种写法之所以不报错,是因为在浏览器环境,所有全局变量都是 window 对象的属性。 window.a 的含义就是读取 window 对象的 a 属性,如果该属性不存在,就返回 undefined ,并不会报错。

需要注意的是,后二种写法有漏洞,如果 a 属性是一个空字符串(或其他对应的布尔值为 false 的情况),则无法起到检查变量是否声明的作用。正确的做法是可以采用下面的写法。

// 写法一
if (window.a === undefined) {
// ...
}

// 写法二
if ('a' in window) {
// ...
}

2.3 属性的赋值

点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。

o.p = 'abc';
o['p'] = 'abc';

2.4 查看所有属性

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

var o = {
key1: 1,
key2: 2
};

Object.keys(o);
// ['key1', 'key2']

2.5 属性的删除

删除一个属性,需要使用 delete 命令。

  • 一旦使用 delete 命令删除某个属性,再读取该属性就会返回 undefined ,而且 Object.keys 方法返回的该对象的所有属性中,也将不再包括该属性:

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

    delete o.p // true
    o.p // undefined
    Object.keys(o) // []

  • 删除不存在的属性,仍未true。因此,delete命令只能用来保证某个属性的值为undefined,而无法保证该属性是否真的存在

    var o = {};
    delete o.p // true

  • 只有一种情况, delete 命令会返回 false ,那就是该属性存在,且不得删除。

    可以通过 configurable: false 来配置属性不可修改

  • delete 命令只能删除对象本身的属性,不能删除继承的属性

2.6 in运算符

in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回 true ,否则返回 false

in 运算符不能识别对象继承的属性。如果使用它来判断继承的属性,也会返回true:

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

'toString' in o // true

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

待确定,、、、、、、是否任意属性都会返回true??????

继承的属性怎么理解??是新创建的对象属性?还是java中继承某个类

2.7 for…in循环

for...in 循环用来遍历一个对象的全部属性,包括自身的和继承的

var o = {a: 1, b: 2, c: 3};

for (var i in o) {
console.log(o[i]);
}

// 1
// 2
// 3

// 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

如果只想遍历对象本身的属性,可以使用hasOwnProperty方法,在循环内部做一个判断:

for (var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
// name

或者新建一个继承 null 的对象。由于 null 没有任何属性,所以新对象也就不会有继承的属性了。

2.8 with语句

with 语句的格式如下:

它的作用是操作同一个对象的多个属性时,提供一些书写的方便。

  • with 区块没有改变作用域,它的内部依然是当前作用域

    因此 with 区块内部的变量,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量:

    var o = {};

    with (o) {
    x = "abc";
    }

    o.x // undefined
    x // "abc"

    上面代码中,对象 o 没有属性 x ,所以 with 区块内部对 x 的操作,等于创造了一个全局变量 x 。正确的写法应该是,先定义对象 o 的属性 x ,然后在 with 区块内操作它:

    var o = {};
    o.x = 1;

    with (o) {
    x = 2;
    }

    o.x // 2

  • with 语句的一个很大的弊病,就是绑定对象不明确

    with (o) {
    console.log(x);
    }

    单纯从上面的代码块,根本无法判断 x 到底是全局变量,还是 o 对象的一个属性。这非常不利于代码的除错和模块化,编译器也无法对这段代码进行优化,只能留到运行时判断,这就拖慢了运行速度。因此,建议不要使用 with 语句,可以考虑用一个临时变量代替 with :

    with(o1.o2.o3) {
    console.log(p1 + p2);
    }

    // 可以写成

    var temp = o1.o2.o3;
    console.log(temp.p1 + temp.p2);

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » JS学习-对象

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址