1、属性普通定义
// var a = "a";
// console.log(window.a)
// console.log(a)
//基本的属性定义形式
var key = "wife";
var key2 = "son";
var obj = {
name:"damu",
[key2]:"小达姆"
};
obj.age = 18;
obj[key]="冬雨";
console.log(Object.getOwnPropertyDescriptor(obj,"name"))
2、属性数据描述符
// writable;value;enumerable;configurable : 属性描述符
var damu = {name:"达姆"};
//wife 可以称为是 damu的数据描述符属性
Object.defineProperty(damu,"wife",{
writable:false, //当前这个属性的值是否可以修改
value:"冬雨", //当前这个属性的值
enumerable:false,//当前这个属性是否可枚举(是否可以出现在对象的for in循环中)
configurable:false//当前这个属性是否可配置(能不能重新定义 能不能删除)
})
//静默失败
// damu.wife="老付";
// delete damu.wife
for(var key in damu){
console.log(key);
}
Object.defineProperty(damu,"wife",{
writable:true, //当前这个属性的值是否可以修改
value:"冬雨", //当前这个属性的值
enumerable:true,//当前这个属性是否可枚举(是否可以出现在对象的for in循环中)
configurable:true//当前这个属性是否可配置(能不能重新定义 能不能删除)
})
3、属性访问描述符
// writable;value;enumerable;configurable : 属性描述符
var damu = {
name:"达姆",
get age(){
return this.__age__
},
set age(val){
if (val<0){
val = 0;
}else if(val>150){
val = 150;
}
this.__age__ = val
}
};
var damu = {name:"达姆"}
//age 可以称为是 damu的访问描述符属性
Object.defineProperty(damu,"age",{
// writable:false,
// value:123,
get:function () {
return this.__age__
},
set:function (val) {
if (val<0){
val = 0;
}else if(val>150){
val = 150;
}
this.__age__ = val
},
enumerable:false,
configurable:false
})
damu.age = 120000;
console.log(damu.age);
console.log(damu.__age__);
4、属性的存在性检查
var obj = {a:'a',b:'b'};
//关键字可以访问原型链
console.log("toString" in obj)
//方法不可以访问原型链
console.log(obj.hasOwnProperty("toString"))
console.log(Object.getOwnPropertyNames(obj))
5、对象不变性
01、常量属性
Object.defineProperty
var obj = {
name:'老付'
};
Object.defineProperty(obj,"wife",{
writable:false,
value:"陪悦",
configurable:false,
enumerable:true
})
obj.wife2 = "小乐"
obj.wife = "安妮"
console.log(obj);
02、禁止对象扩展
Object.preventExtensions(obj)
var obj = {name:'老付'};
Object.preventExtensions(obj)
obj.name="小老付"
obj.wife="老张";
delete obj.name
console.log(obj);
03、密封对象
Object.seal(obj)
var obj = {name:'老付'};
Object.seal(obj)
obj.name = "xxx"
delete obj.name
console.log(obj);
04、冻结对象
Object.freeze(obj)
//方法不可以访问原型链 也影响不了对象的深层属性
var obj = {
name:'老付',
wife:{
name:"xxx"
}
};
Object.freeze(obj)
obj.wife = "陪悦";
console.log(obj);
05、利用递归实现深度冻结对象属性
var obj = {
a:{
b:{
c:{
d:"d"
}
}
},
name:"xx"
}
//深度冻结
Object.deepFreeze = function (obj) {
var propNames = Object.getOwnPropertyNames(obj)
propNames.forEach((item)=>{
var val = obj[item];
if(typeof val === "object" && val !==null){
// 说明val肯定是对象
Object.deepFreeze(val)
}
})
//浅冻结
Object.freeze(obj)
}
Object.deepFreeze(obj);
obj.a.b.c.d="xxxx";
console.log(obj);
6、原型&原型链
01、函数的定义
// function add(a,b) {return a+b}
// var add = function(a,b){return a+b}
const add = new Function('a', 'b', 'return a + b');
console.log(add(1, 2));
02、属性的设置
// Object.prototype.a = "Object_prototype_a"
Object.defineProperty( Object.prototype,"a",{
// writable:false,
// value:"a",
enumerable:true,
configurable:true,
set:function (val) {
}
})
var obj = {};
obj.a = "a";
console.log(obj);
03、方法的重写
// arr.__proto__ --> obj.__proto__ --> Array.prototype.__proto__ --> Object.prototype.__proto__ -->null
var obj = {toString:function () {return "冬雨 ❤ 达姆"}};
obj.__proto__ = Array.prototype;
var arr = ["老付","陪悦","安妮","小乐","丹丹"];
arr.__proto__ = obj;
console.log(arr.toString())
// console.log(Object.prototype.toString.call(arr))
04、继承
04-1构造函数的继承
function Person(age,name){
this.age=age;
this.name=name;
this.eat=function(){
console.log("吃很多")
}
}
function Teacher(course,age,name){
Person.call(this,age,name);
this.course =course;
}
function Student(num,age,name){
Person.call(this,age,name);
this.num =num;
}
var damu = new Teacher("qkl",18,"达姆");
damu.eat();
var damu2 = new Student(1,18,"达姆");
damu2.eat();
console.log(damu,damu2);
04-2原型链继承
Person.prototype.eat=function(){
console.log("吃很多")
}
function Person(age,name){
this.age=age;
this.name=name;
}
Teacher.prototype = new Person();
/*Teacher.prototype.constructor = Teacher;
console.log(Teacher.prototype.constructor);*/
function Teacher(course,age,name){
this.course =course;
}
Student.prototype = new Person();
function Student(num,age,name){
this.num =num;
}
var damu = new Teacher("qkl",18,"达姆");
var damu2 = new Student(1,18,"达姆");
damu.eat();
damu2.eat();
console.log(damu,damu2);
console.log(damu.constructor);
04-3组合继承
/*
js中的原型链继承只有一个目的
降低创建对象的开销!!!
*/
Person.prototype.eat=function(){
console.log("吃很多")
}
function Person(age,name){
this.age=age;
this.name=name;
}
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
console.log(Teacher.prototype.constructor);
function Teacher(course,age,name){
Person.call(this,age,name);
this.course =course;
}
Student.prototype = new Person();
function Student(num,age,name){
Person.call(this,age,name);
this.num =num;
}
var damu = new Teacher("qkl",18,"达姆");
var damu2 = new Student(1,18,"达姆");
damu.eat();
damu2.eat();
console.log(damu,damu2);
console.log(damu.constructor);
04-4对象级别的继承
var father={name:"马云"};
var son = Object.create(father)
debugger
7、笔记
原型&原型链
显示原型: 所有的函数都有显示原型(可以认为显示原型是一个Object类型的对象)
隐式原型: 所有的对象都有隐式原型
对象的隐式原型指向其构造函数的显示原型
原型链是隐式原型链
原型链的头是 Object.prototype.__proto__
属性查找与设置规范
属性查找:
找obj.a; 先在obj中的直接属性内找;如果找到则使用找到的值;如果没有找到;上原型链
如果整条原型链都没有对应的属性 则返回undefined
属性设置
obj.a = 'a' ; 无论如何改动的都是obj对象;如果obj没有a属性则设置一个;如果obj有a属性则修改