娄底市建设银行宣传部网站,wordpress中文相册插件,北京市朝阳区住房建设网站,网站的html面向对象编程
面向对象编程是一种使用包含数据和行为的对象来模拟现实世界实体的编程范式。这种方法便于封装、继承和多态性#xff0c;代码更易管理、复用和扩展 在JS当中所体现的主要来源于封装和继承#xff0c;封装在日常处处都会用到#xff0c;我们使用函数方法就是一…面向对象编程
面向对象编程是一种使用包含数据和行为的对象来模拟现实世界实体的编程范式。这种方法便于封装、继承和多态性代码更易管理、复用和扩展 在JS当中所体现的主要来源于封装和继承封装在日常处处都会用到我们使用函数方法就是一种封装 继承则是我们的重点原型链的概念就来自于继 创建对象的方式 new Object() new Object() 是 JavaScript 的原生构造函数调用时会创建一个空对象并返回该对象
let obj new Object() // 创建一个对象
obj.name zhangsan // 给对象添加属性和方法
obj.sayName function(){ // 给对象添加方法console.log(this.name) // this指向当前对象
}
obj.sayName() // 调用方法字面量方式创建对象 最简洁直观的方式适合定义单例对象或简单数据结构
let obj { // 创建一个对象name: zhangsan, // 添加属性和方法sayName: function(){ // 添加方法console.log(this.name) // this指向当前对象}
}
obj.sayName() // 调用方法工厂函数 工厂函数是一种创建对象的函数返回一个新对象而不是使用 this,无法使用 instanceof 检查类型,无法使用原型链
function createPerson(name, age) {return {name,age,greet() {console.log(Hello, ${this.name}!);}};
}
const bob createPerson(Bob, 25);
bob.greet(); // 输出: Hello, Bob!Object.create() Object.create() 方法用于创建一个新对象使用现有的对象来提供新创建的对象的__proto__。
let obj Object.create(null) // 创建一个对象原型为null
obj.name zhangsan // 添加属性和方法
obj.sayName function(){ // 添加方法console.log(this.name) // this指向当前对象
}
obj.sayName() // 调用方法const proto {
greet() {console.log(Hello, ${this.name}!);
}
};
const john Object.create(proto);
john.name John; // 添加自身属性
john.greet(); // 输出: Hello, John!
构造函数 构造函数是一种特殊的函数用于创建和初始化对象。在 JavaScript 中构造函数通常以大写字母开头用于区分普通函数。 通过 new 调用函数创建对象实例适合批量生成结构化对象
function Person(name, age) {this.name name;this.age age;
}
Person.prototype.greet function() {console.log(Hello, ${this.name}!);
};
const alice new Person(Alice, 30);
alice.greet(); // 输出: Hello, Alice!类语法 语法糖形式更贴近传统面向对象语言内部仍基于原型链支持继承extends、静态方法static、访问器get/set方法自动绑定到原型不可枚举
class Person {constructor(name, age) {this.name name;this.age age;}greet() {console.log(Hello, ${this.name}!);}
}
const charlie new Person(Charlie, 28);原型继承优化寄生组合继承 解决组合继承中父类构造函数重复调用的问题是继承的最佳实践。方法通过原型链共享属性独立初始化。避免父类构造函数重复执行组合继承的缺陷
function Parent(name) {this.name name;
}
Parent.prototype.say function() {console.log(this.name);
};
function Child(name, age) {Parent.call(this, name); // 继承属性this.age age;
}
Child.prototype Object.create(Parent.prototype); // 继承方法
Child.prototype.constructor Child; // 修复构造函数指向
const child new Child(Tom, 10);
属性描述符
数据属性描述符是一种用于控制对象属性行为的工具。它提供了对属性的更细致管理允许开发者定义属性的各种特性。数据属性描述符包含了几个特殊的属性或称为“特性”这些特性决定了对象属性的行为方式
通过属性描述符可以精准的添加或修改对象的属性也就是一种特性属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改
Object.defineProperty
定义 Object.defineProperty() 方法用于直接在一个对象上定义一个新属性或者修改一个对象的现有属性并返回这个对象。
Object.defineProperty(obj, prop, descriptor)
// obj要定义属性的对象
// prop要定义或修改的属性的名称或者Symbol(后面会讲解这个类型)
// descriptor要定义或修改的属性描述符
const obj {}; // 创建一个空对象
Object.defineProperty(obj, name, { // 定义属性value: zhangsan, // 属性值writable: true, // 是否可写enumerable: true, // 是否可枚举configurable: true // 是否可配置
});
console.log(obj.name); // 输出: zhangsan属性描述符分类 属性描述符分为数据描述符和存取描述符二者不可混用数据描述符直接控制值 value属性值默认 undefinedwritable是否允许赋值修改默认 falseenumerable是否可枚举如 for…in 能否遍历默认 falseconfigurable是否可删除或重新配置特性默认 false
const obj {}; // 创建一个空对象
Object.defineProperty(obj, id, {value: 1001,writable: false, // 不可修改configurable: false // 不可删除或重定义
});
console.log(obj.id); // 输出: 1001
obj.id 1002; // 尝试修改无效
delete obj.id; // 尝试删除无效
consloe.log(obj); 存取描述符通过函数拦截操作 get获取属性值的函数默认 undefinedset设置属性值的函数默认 undefinedenumerable是否可枚举如 for…in 能否遍历默认 falseconfigurable是否可删除或重新配置特性默认 false
const obj {}; // 创建一个空对象
Object.defineProperty(obj, age, {get() { // 获取属性值的函数return this._age; // 返回私有属性}, set(newValue) { // 设置属性值的函数this._age newValue; // 设置私有属性},
})
console.log(obj.age); // 输出: undefined
obj.age 20; // 设置属性值
console.log(obj.age); // 输出: 20数据属性描述符有如下四个特征
Configurable表示属性是否可以通过delete删除属性是否可以修改它的特性或者是否可以将它修改为存取属性描述符 对象上定义某个属性时这个属性的Configurable为true通过属性描述符定义一个属性时这个属性的Configurable默认为false Enumerable表示属性是否可以通过for-in或者Object.key()返回该属性; 对象上定义某个属性时这个属性的Enumerable为true通过属性描述符定义一个属性时这个属性的Enumerable默认为false Writable表示是否可以修改属性的值 对象上定义某个属性时这个属性的Writable为true通过属性描述符定义一个属性的时候这个属性的Writable为false value属性的value值读取属性时会返回该值修改属性时会对其进行修改 默认情况下这个值是undefined
var obj {name:sumu,age:18
}//name和age虽然没有使用属性描述符来定义但是它们也是具备对应的特性的以下是对应的默认值
//value:赋值的value
//configurable:true
//enumerable:true
//writable:true
// 属性描述符添加另外一个属性address
//数据属性描述符
Object.defineProperty(obj,address,{//很多配置value:上海市,//默认值undefined//该属性不可删除不可修改。不可以重新定义属性描述符configurable:false//默认值false//该特性是配置对应的属性(address)是否是可以枚举的enumerable:true,//默认值false//该特性是否可以赋值writable:false//默认值false
})delete obj.name
console.log(obj)//{ age: 18 }name被成功删除
delete obj.address
console.log(obj.address);//上海市 没删除掉因为我们设置了不可配置configurable:false//测试enumerable的作用
console.log(obj)
for(var key in obj){console.log(key,for遍历);//如果enumerable为false则只会出来name和ageaddress只有设置为true的时候才会出来
}
console.log(Object.keys(obj),keys的作用);
//enumerable前后对比
//[ name, age ] keys的作用(enumerable:false)
//[ name, age, address ] keys的作用(enumerable:true)//测试writable的作用
obj.address 北京市
console.log(obj.address);//上海市新的内容不可写入。如果我们不设置value为上海市则在不可写入的情况下显示undefined存取属性描述符有如下四个特征
Configurable表示属性是否可以通过delete删除属性是否可以修改它的特性或者是否可以将它修改为存取属性描述符 对象上定义某个属性时这个属性的Configurable为true通过属性描述符定义一个属性时这个属性的Configurable默认为false Enumerable表示属性是否可以通过for-in或者Object.key()返回该属性;get获取属性时会执行的函数默认为undefinedset设置属性时会执行的函数默认为undefined
var obj {name:sumu,age:18,_address:上海市//_开头表示私有的不希望被人看到。我们就通过get来使用address代替掉_address。别人就通过address调用我们而不是使用_address调用
}//当我们使用get、set不使用value和writable的时候叫做存取属性描述符
//使用场景1.隐藏某一个私有属性不希望直接被外界使用和赋值
//2.如果我们希望截获某一个属性它访问和设置值的过程时我们也会使用存储属性描述符
Object.defineProperty(obj,address,{//很多配置enumerable:true,configurable:true,//value跟writable与get、set不能共存// value:上海市,// writable:true,get:function(){console.log(获取了一次address的值)return this._address//将_address这个属性隐藏起来},set:function(value){bar()//这样就截获了它获取值的过程这是Vue2响应式的原理//当我们如下对obj.address进行赋值的时候值就通过形参传递了进来我们在这里进行赋值的操作this._address value}
})console.log(obj)//{ name: sumu, age: 18, address: [Getter/Setter] }
console.log(obj.address);//上海市 获取了一次address的值
obj.address 北京市//我们使用的是address而不是_address了哦注意这里的变化_address的值并没有改变,是私有属性
console.log(obj.address);//北京市function bar(){console.log(设置了一次address的值)
}对象上同时定义多个属性 - Object.defineProperties
定义 Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性并返回该对象。
Object.defineProperties(obj, props)
// obj要定义属性的对象
// props要定义或修改的属性描述符的集合
const obj {//私有属性(js中没有严格意义上的私有属性依旧可以通过obj._age访问到但是外人是不知道这个隐藏起来的属性只知道他的替代obj.age)_age:20
};
Object.defineProperties(obj, { // 定义多个属性name: { // 定义属性value: sumu, // 属性值writable: true, // 是否可写enumerable: true, // 是否可枚举configurable: true // 是否可配置},address: { // 定义属性value: 上海市, // 属性值writable: true, // 是否可写enumerable: true, // 是否可枚举configurable: true // 是否可配置},age:{configurable:false,enumerable:false,get:function(){return this._age},set:function(value){this._age value}}
});
console.log(obj.name); // 输出: sumu
console.log(obj.address); // 输出: 上海市console.log(obj.age)//20
console.log(obj,为了看age的不可枚举是否生效);//{ _age: 20, name: sumu } 这是为了看age的不可枚举是否生效
obj.age 18
console.log(obj.age);//18 对象方法
getOwnPropertyDescriptor - 获取对象上指定属性的描述符getOwnPropertyDescriptors- 获取对象上所有属性的描述符defineProperty - 定义或修改对象上的一个属性defineProperties - 定义或修改对象上的多个属性preventExtensions - 防止对象扩展
//返回指定对象上一个自有属性对应的属性描述符
Object.getOwnPropertyDescriptor(obj, prop)
//返回一个对象该对象包含了目标对象所有自有属性的属性描述符
Object.getOwnPropertyDescriptors(obj)var obj {names: 苏木,age: 18
}
console.log(Object.getOwnPropertyDescriptor(obj, names));
console.log(Object.getOwnPropertyDescriptors(obj));Object的方法对 对象的限制
禁止对象扩展新属性preventExtensions 给一个对象添加新的属性会失败(在严格模式下会报错) 密封对象不允许配置和删除属性seal 实际是调用preventExtensions并且将现有属性的configurablefalse 冻结对象不允许修改现有属性freeze 实际上是调用seal并且将现有属性的writablefalse
var obj {names: sumu,age: 18
};// 禁止对象扩展新属性
Object.preventExtensions(obj);
obj.newProperty new; // 尝试添加新属性这将失败
console.log(obj.newProperty); // 输出undefined在严格模式下这会抛出错误
console.log(obj); // 输出{ names: sumu, age: 18 }新属性未添加var obj {names: sumu,age: 18
};// 密封对象不允许配置和删除属性
Object.seal(obj);
obj.names new; // 尝试修改属性值这将成功
delete obj.age; // 尝试删除属性这将失败
console.log(obj.names); // 输出new属性值已修改
console.log(obj.age); // 输出18属性未删除
console.log(obj); // 输出{ names: new, age: 18 }属性未删除// 冻结对象不允许修改现有属性
Object.freeze(obj);
obj.names MOS; // 尝试修改属性值这将失败
console.log(obj.names); // 输出new因为freeze后属性值不可更改