第八章 对象,类与面向对象编程
对象
两种创建对象的方法,第一种是new Object() 第二种就是对象字面量,相比而言,第二种用的更多
//这种方法是new一个实例
let person = new Object();
person.name = "Nicholas";
person.age = 29;
//对象字面量
let person = {
name:"Nicholas",
age:"29"
}
属性分两种:数据属性和访问器属性
数据属性:数据属性包含数据值
数据属性有四种内部特性来描述行为:
[[Configurable]]:表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它修改为访问器属性。
[[Enumberable]]:表示属性是否可以通过for-in循环返回
[[Writable]]:表示属性的值是否可以被修改
[[Value]]:包含属性实际的值
修改属性的默认特性,就要使用到Object.defineProperty()方法
传入三个参数:要添加属性的对象,属性名,要修改哪些内部特性
let person = {};
Object.defineProperty(person,"name",{
writable:false, //表示这个属性不可修改
value:"jack"
});
console.log(person.name) //jack
person.name = 'jim';
console.log(person.name) //jack 因为这个属性已经被设置成了不可修改
访问器属性不包含数据值
访问器属性有四种内部特性来描述行为:
[[Configurable]]:表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它修改为数据属性。
[[Enumberable]]:表示属性是否可以通过for-in循环返回
[[Get]]:获取函数,在读取属性时调用,默认值为undefined
[[Set]]:设置函数,在写入属性时调用,默认值为undefined
修改属性的默认特性,就要使用到Object.defineProperty()方法
传入三个参数:要添加属性的对象,属性名,要修改哪些内部特性
//访问器属性典型使用场景就是设置一个属性值会导致一些其他变化发生
let book = {
year_:2017, //这里下划线表示一个伪私有属性,不希望被外界访问到
edition:1
};
Object.defineProperty(book,"year",{
get(){
return this.year_; //用获取函数返回这个值 这里就是简单用一下,写不写这部分不影响下面代码的运行
},
set(newValue){
if(newValue>2017){
this.year_ = newValue; //赋上新值
this.edition += newValue - 2017 //改变版本号
}
}
});
book.year = 2018; //赋值
console.log(book.edition); //版本号被改成了2
合并对象【重点,实际开发中常常用到】
Object.assign() 方法 把多个对象合并在一起
dest = {};
result = Object.assign(dest,{a1:1},{a2:2});
console.log(result) //{a1:1,a2:2} 把这三个对象合并在一起
还可以合并覆盖相同属性
dest = {id:"dest"};
result = Object.assign(dest,{id:"scr1",a:"foo"},{id:"src2",b:"bar"});
console.log(result) //{id:"src2",a:"foo",b:"bar"} 覆盖相同属性,合并不同属性
增强的对象语法
就是ES6新增了语法糖,方便处理对象
1.属性值简写(就是k,v一致省略v)
let name = "Matt";
let person = {
name //这是简写,完整写法就是name:name
}
console.log(person) //{name:"Matt"}
2.可计算属性(就是方便直接动态命名属性)
用中括号[]包围对象属性,这是javascript表达式而不是普通字符串
const nameKey = 'name';
let person = {
[nameKey]:'Matt'
};
console.log(person); //{name:'Matt'}
3.简写方法名
//以前是一个方法名+:+一个匿名函数来定义方法
let person = {
sayName:function(name){
console.log(name)
}
};
//现在因为ES6新增的方法就可以写成
let person = {
sayName(name){
console.log(name)
}
}
对象解构
就是使用与对象匹配的结构来实现对象属性的赋值
let person = {
name:'Matt',
age:'27'
};
let {name:personName,age:personAge} = person //这么写就是看起来与对象匹配,实际可以这么看,personName:name,person:age
console.log(personName); //Matt
console.log(personAge); //27
构造函数 (是用于创建特定类型对象的)
1.构造函数的名称要大写
2.任何函数只要使用new操作符就是构造函数,其他的就是普通函数,函数都是差不多的,只不过用来创建对象时,函数的调用方式不同而已
//构造函数名大写
function Person(name,age,job){
this.name = name,
this.age = age,
this.job = job,
this.sayName = function(){
console.log(this.name)
}
}
//调用构造函数时要new一个实例
let person1 = new Person('Nicholas',29,'softerware engineer');
let person2 = new Person('Grey',27,'Doctor');
person1.sayName(); //Nicholas
person.sayName(); //Grey
我认为构造函数是为了方便解决处理同一类型的数据
原型模式【重点】 (一想到原型模式,我就想到vuex的状态管理,都是共享,但是完全不同)
prototype属性,这个属性是一个对象,简称原型对象
函数的prototype属性是一个原型对象,在这个原型对象上可以加其他属性,加上的属性可以被实例共享
容易混淆的两个属性:
__proto __指向当前对象的原型,prototype是函数才具有的属性
function Person(){}
Person.prototype.name = 'proto' //函数的原型上加一个name属性
let person1 = new Person();
console.log(person1.name) // proto
console.log(person1.__proto__ === Person.prototype) //true 这个实例对象上的原型跟函数的原型是同一个原型
对象迭代:
1.Object.values() 返回对象值的数组
2.Object.entries() 返回键值对的数组
const a = {
foo:"bar",
baz:"1",
qux:{},
};
console.log(Object.values(a)); //["bar",1,{}]
console.log(Object.entries(a)) //[["foo","bar"],["baz",1],["quz",{}]]
网友评论