对象
无序的数据集合,由若干个“键值对”(key-value)构成。
键值对由键名和键值组成,每个键值对之间用逗号分隔。
- 键名是字符串,不是标识符。
- 若引号省略,则键名按标识符格式命名,但它仍然是字符串。
创建对象的方式
- new Object()
- 对象字面量
//第一种
var person = new Object()
person.name = 'jane'
person.age = 18
//第二种
var person = {
name: 'jane'
age: 18
}
属性的方法(增删改查)
读取属性的方法 (读)
(重点)
点表示法
用来访问对象的属性和方法。
只能接受字面量的成员名字,不接受变量作为名字。
数值键名不能用点表示法,如obj.0xFF会被当成小数点。
var person = {
name : {
first : 'Bob',
last : 'Smith'
},
age : 18,
5 : 'number'
}
console.log(person.age); // 18 age是字符串
console.log(person.name.first); // Bob
console.log(person.5); // 会报错
Object.keys(person);//["5", "name", "age"]
括号表示法
另一种访问属性的方式。
将要访问的属性以字符串的形式放入方括号中。
键名必须加引号否则会被当成变量,数字键可以不加。
console.log(person['age']) //18
console.log(person['name']['first']) // Bob
console.log(person[5]) //number
优点:括号表示法可以通过变量来访问属性。
var a = 'xxx';
var obj = {
xxx: 1234 //[a]作为变量使用
}
console.log(obj);//{xxx: 1234}
var a = 'xxx';
var obj = {};
obj.xxx = 'jane';
obj.a//undefined,访问不到对应的属性,点表示法不接受变量作为名字
obj[a]//"jane" 通过变量访问属性
//obj[a] 等同于 obj.xxx 等同于 obj['xxx']
给属性赋值的方法 (增/改)
- 点表示法
- 括号表示法
var o = new Object();
o.name = 'jane';
o['age'] = 18;
console.log(o); //{name: "jane", age: 18}
- 批量赋值
Object.assign(obj,{})
var o = new Object();
Object.assign(o,{a:1, b:2});
console.log(o);//{a: 1, b: 2}
- 无法通过自身修改或增加 继承属性
var obj1 = {};
obj1.toString = 'xxx';
若非要改变继承属性,可通过原型链改变
obj1.__proto__.toString = 'hello';
Object.create()
创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。(新对象继承现有对象的原型和属性)
var common = {name: 'jane', age: 18};
var person = Object.create(common);
person;
删除属性 (删)
delete obj.name
无法认定某个属性是否存在的,只能保证读取这个属性肯定得到undefined。(即删除不存在的属性它也不报错)
var obj = {
name : 'jane',
age : 18
}
//判断是否含有属性名
'name' in obj === false;//true 则不含name属性名
'name' in obj === undefined;// 不能判断属性名,只能判断属性值
//删除属性名和属性值
delete obj.name;
console.log(obj); //{age: 18}
//仅删除属性值
obj.name = undefined;
查看所有属性(查)
Object.keys(obj)
var obj = {
name : 'jane',
age : 18
}
Object.keys(obj); //["name", "age"]
查看属性值
Object.values(obj)
var obj = {
name : 'jane',
age : 18
}
Object.values(obj);//["jane", 18]
查看自身属性和继承属性
console.dir(obj)
var obj = {
name : 'jane',
age : 18
}
console.dir(obj);
判断自身属性还是继承属性
obj.hasOwnProperty('属性名')
var obj = {
name : 'jane',
age : 18
}
obj.hasOwnProperty('name');//true
obj.hasOwnProperty('toString');//false
检查变量是否被声明
var a = 1
if(a){
console.log('ok')
} // ok
if(window.a){
console.log('ok')
} // ok
if(b){
console.log('ok')
} // 报错
if(window.b){
console.log('ok')
} // undefined 即找不到这个属性
模式
工厂模式
function createPerson(name,age,sex){
var o = new Object();
o.name = name;
o.age = age;
o.sex = sex;
return o;
}
var person1 = createPerson('Bob',18,'female');
console.log(person1)
优点:
- 解决了创建多个相识对象的问题
缺点:
- 没有解决对象识别的问题(识别对象的类型)
构造函数
function Person(name,age,sex){
this.name = name
this.age = age
this.sex = sex
this.sayName = function(){
console.log(this.name)
}
//相当于 this.sayName = new Function("console.log(this.name)")
//两个方法不是同一个Function的实例
}
var person1 = new Person('Bob',18,'male')
console.log(person1)
person1.sayName()//"Bob"
var person2 = new Person('Jane',20,'female')
console.log(person2)
person2.sayName()//"Jane"
console.log(person1.sayName == person2.sayName)//false
不同实例上的同名函数不相等
function Person(name,age,sex){
this.name = name
this.age = age
this.sex = sex
this.sayName = sayName
}
//设置成全局函数
function sayName(){
console.log(this.name)
}
var person1 = new Person('Bob',18,'male')
console.log(person1)
person1.sayName()
var person2 = new Person('Jane',20,'female')
console.log(person2)
person2.sayName()
console.log(person1.sayName == person2.sayName)//true
缺点:
- 需要定义很多方法,就需要定义多个全局函数
与工厂模式区别:
- 没有显示创建对象
- 直接将属性和方法赋值给了this对象
- 没有return语句
new运算符
var person1 = new Person('Bob',18,'female');
console.log(person1)
- 创建空的对象{}
var person = new Object(); - 设置 该对象的构造函数到另一个对象(原型链)
person._proto_ = Person.prototype; - 将创建的对象
person作为this的上下文 - 判断返回值,若没有返回对象,则返回this
原型模式
function Person(){
}
Person.prototype.name = 'Bob'
Person.prototype.age = 18
Person.prototype.sayName = function(){
console.log(this.name)
}
var person1 = new Person()
console.log(person1)
person1.sayName()//"Bob"
var person2 = new Person()
person2.sayName()//"Bob"
console.log(person1.sayName === person2.sayName)//true
优点:
- 让所有实例共享它的属性和方法
JSON
JavaScript Object Notation 是一种用于数据交换的文本格式
格式
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
- 简单类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。
- 字符串必须使用双引号表示,不能使用单引号。
- 对象的键名必须放在双引号里面。
- 数组或对象最后一个成员的后面,不能加逗号。
注意
空数组和空对象都是合格的 JSON 值,null本身也是一个合格的 JSON 值。
方法
JSON.stringify()
用于将一个值转为字符串,并且可以被JSON.parse方法还原。
JSON.stringify('abc')//""abc""
//双引号可以让 JavaScript 引擎知道,foo是一个字符串,而不是一个变量名
JSON.stringify(1)//"1"
JSON.stringify([])//"[]"
JSON.stringify({})//"{}"
JSON.stringify([1,2,'hello'])//"[1,2,"hello"]"
JSON.stringify(name : 'zhang')//"{"name":"zhang"}"
比较: 对于原始类型的字符串,转换结果会带双引号。
JSON.stringify('abc') === "abc"//false
JSON.stringify('abc') === "\"abc\""//true
- 对象中,有成员的值是undefined、函数等,这个成员会被JSON.stringify()过滤。
- 数组中,成员是undefined、函数等,则这些值被转成null。正则对象会被转成空对象。
var obj = {
a : undefined,
b : function(){}
}
JSON.stringify(obj) // "{}"
var arr = [undefined,function(){}]
JSON.stringify(arr) // "[null,null]"
JSON.stringify(/foo/) // "{}"
JSON.parse()
用于将JSON字符串转化成对象。
JSON.parse('"abc"');//"abc"
JSON.parse('true');//true
JSON.parse('{}');//{}
JSON.parse('[1,2,"hello"]');//[1, 2, "hello"]
JSON.parse("'String'") // (对象的键名没有放在双引号内)Unexpected token ' in JSON at position 0
JSON.parse(JSON.stringify([1,2,"hello"])) == [1,2,"hello"];//false
//通过JSON转化成字符串再还原的字符串[1,2,"hello"]已经不是原来的字符串了。
深拷贝的另一种写法
var obj = {
name: 'Jane',
age: 3,
friends: ['aa', 'bb', 'cc']
}
var obj2 = JSON.parse(JSON.stringify(obj))
obj.age = 4
console.log(obj2.age) // 3