1.对象的创建
2.属性描述符
3.对象方法补充
4.构造函数创建对象
1)new的时候发生了什么
2)对象原型
3)函数原型
4)创建对象的内存表现
5)把prototype赋值为新的对象发生了什么,new的时候会创建多个函数,影响内存,如何解决
6)constructor
7)原型链
8)继承
5.class类
1.对象的创建
// 对象的创建 四种方式
// 第一种
let obj={a:1}
console.log(obj.a);//1
// 第二种
let obj1=new Object()
obj1.a=1
console.log(obj1.a);//1
// 第三种 下文会讲
function ObjFn(){
this.a=1
}
let obj2=new ObjFn()
console.log(obj2.a);//1
// 第四种 下文会讲
class Objclass{
a=2
}
let obj3=new Objclass()
console.log(obj3.a);//2
2.属性描述符
1)内容:包括数据属性和描述属性:
2)数据属性可以设置configurable,enumerable,value,writable
3)描述属性可以设置configurable,enumerable,set,get
如果名字记不住可以通过Object里面的defineProperty的PropertyDescriptor查看 注意数据描述符里面是不能设置get和set的 描述属性里面不能设置value和writable 因为这两对属性是互斥的
4)关于各个属性的含义
configurable:是否可以删除和修改
enumerable:是否可以被遍历
value:属性对应的值
writable:是否可获取
set:对某个属性设置值的时候,执行的方法
get:对某个值获取的时候执行的方法
5)对于他们的默认值:
let obj={
a:1
}
//设置属性描述符
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
//{ value: 1, writable: true, enumerable: true, configurable: true }
//获取属性描述符
Object.defineProperty(obj,'b',{})
console.log(Object.getOwnPropertyDescriptor(obj,'b'));
//{ value: undefined, writable: false, enumerable: false, configurable: false}
3.对象方法
1).Object.definePropertiy():设置单个描述符
let obj={a:21}
Object.defineProperty(obj,'b',{
configurable:true,
enumerable:true,
value:'1',
writable:true
})
console.log(obj);//{ a: 21, b: '1' }
2).Object.defineProperties():设置多个描述符
let obj={a:21}
Object.defineProperties(obj,
{
'b':{
configurable:true,
enumerable:true,
value:'1',
writable:true
},
'c':{
configurable:true,
enumerable:true,
value:'2',
writable:true
}
}
)
console.log(obj);//{ a: 21, b: '1', c: '2' }
3).Object.getOwnPropertyDescriptor():获取单个描述符
let obj={a:21}
Object.defineProperties(obj,
{
'b':{
configurable:true,
enumerable:true,
value:'1',
writable:true
},
}
)
console.log(Object.getOwnPropertyDescriptor(obj,'b'));
// b: { value: '1', writable: true, enumerable: true, configurable: true },
4).Object.getOwnPropertyDescriptors():获取全部描述符
let obj={a:21}
Object.defineProperties(obj,
{
'b':{
configurable:true,
enumerable:true,
value:'1',
writable:true
},
}
)
console.log(Object.getOwnPropertyDescriptors(obj));
// {
// a: { value: 21, writable: true, enumerable: true, configurable: true },
// b: { value: '1', writable: true, enumerable: true, configurable: true },
// }
5).Object.preventExtensions() (在严格模式下会报错):禁止对对象添加属性
let obj={a:21}
Object.preventExtensions(obj)
obj.b=3
console.log(obj);//{ a: 21 }
6).Object.seal():禁止对对象添加,修改删除属性,其实是preventExtensions和configurable的结合
let obj={a:21}
Object.seal(obj)
obj.b=3
console.log(obj);//{ a: 21 }
7).Object.feeze():禁止对对象添加/删除/修改/读取值。其实是seal和writable:false的结合
let obj={a:21}
Object.freeze(obj)
obj.b=3
console.log(obj);//{ a: 21 }
8).Object.hasOwnProperty():对象里是否有这个属性,不包括原型链上的属性(原型链后面讲)
let obj={a:21}
// Object.create创造__proto__对象指向obj的对象
let info=Object.create(obj)
info.b=2
console.log(info.hasOwnProperty('a'));//false
console.log(info.hasOwnProperty('b'));//true
9).in/for in:in判断对象里是否有这个属性,包括原型链上的属性(原型链后面讲) for in是循环对象上的属性,包括原型链里面的也会被循环(原型链后面讲)
let obj={
a:21
}
// Object.create创造__proto__对象指向obj的对象
let info=Object.create(obj)
info.b=2
// 原型链上的值也是属于true
console.log('b' in info);//true
console.log('a' in info);//true
// 会对对象以及原型链上的属性都遍历
for(let a in info){
console.log(a);//打印a b
}
10).对象 instanceof 类:原型链上是否有某个类,不能检测基础类型
class Ini{}
function namea(params) {}
let arr=[1,2]
console.log(arr instanceof Array);//true
console.log('a' instanceof String);//false 不能检测基础类型
// 非基础类型都是对象类型构造函数 基础类型都返回false
console.log(arr instanceof Object);//true
console.log(namea instanceof Object);//true
console.log({a:2} instanceof Object);//true
console.log(Ini instanceof Object);//true
console.log('a' instanceof Object);//false
11).对象.isPorototypeOf(对象):后面的对象的原型链上是否有前面那个对象,返回布尔值
var obj = {
name: "why",
age: 18
}
// Object.create创造__proto__对象指向obj的对象
var info = Object.create(obj)
var info1 = Object.create(info)
var inf2 = Object.create(info1)
console.log(obj.isPrototypeOf(inf2))//true
12)Object.getPrototypeOf():获取对象原型
4.构造函数创建对象
//构造函数首字母一般大写是一种默认的规范
function ObjFn(){
this.a=1
this.fn=function(){}
}
//objFn就是构造函数 每次new的时候会构造一个函数
let obj=new objFn()
console.log(obj);//objFn { a: 1 }
1)new的时候发生了什么
2)对象原型和函数原型
每个对象和函数都有一个原型,对象原型可以通过属性__proto__或Object.getPrototypeOf来获取,对于函数原型可以通过属性prototype来获取,在原型对象里面有一个属性constructor会指回构造函数
let obj={a:1}
// 如果是这种创建方式(new Object同理) 原型直接是Object的原型对象
console.log(obj.__proto__);//[Object: null prototype] {}
console.log(obj.__proto__.__proto__);//null 对象是顶级对象 所以对象的原型是null
function ObjFn(){}
let obj1=new ObjFn()
console.log(obj1.__proto__);// {}是ObjFn的原型
console.log(obj1.__proto__.__proto__);//[Object: null prototype] {}
console.log(obj1.__proto__.__proto__.__proto__);//null
class ObjFn1{}
let obj2=new ObjFn1()
console.log(obj2.__proto__);// {}是ObjFn1的原型
console.log(obj2.__proto__.__proto__);//[Object: null prototype] {}
console.log(obj2.__proto__.__proto__.__proto__);//null
对于代码里构造函数new出来的原型链结构图如下:
7)原型链
原型链就是由对象的原型组成的链 如图红色部分就属于原型链,当我们去一个对象获取值的时候,,查找到就返回,如果该对象的原型对象上没有该值,就会去上一层查找该值,直到顶级Object的原型null为止,如果还是没查找到就返回undefined
8)继承
不用class实现继承常见的方式有:原型链继承 借用构造函数继承 父类原型赋值继承 原型式继承 寄生式继承 寄生组合式继承 具体不展开了。
5.class类
类是es6新推出的标准
1)声明
// 首字母大写 默认规范
class Person{}
let Student=class{}
2)constructor extends super
// 首字母大写 默认规范
class Person{
// 属性的定义
a
b='b'
// 函数的定义 由于es6字面量增强 所以可以这样写
foo(){console.log('foo');}
// 当new或super的时候会调用
constructor(a){
console.log('constructor被调用了');
this.a=a
}
}
// extends代表继承
class Student extends Person {
constructor(){
// 调用Person的constructor
super('a')
}
}
let obj=new Student()
console.log(obj);//Student { a: 'a', b: 'b' } 会包含父亲里面有的属性和自身的属性,因为继承了父亲
3)get和set 静态属性 属性命名和函数命名(命名见上2)
// obj.b 取值优先级不是get 而是属性值
class Person{
a=1
b=2
static c=1
get a(){
return this.a
}
set a(value){
this.a=value
}
get b(){
return this.a
}
set b(value){
this.b=value
}
}
let obj=new Person()
console.log(obj.b);// 如果有b=2 则obj.b会取这个2的值 如果没有则会执行get b(){}
console.log(obj);//Person { a: 1, b: 2 } 没有c的属性
console.log(Person.c);//1 static静态属性是可以通过类访问的,但是不能通过new出来的对象访问