当前位置: 首页 > news >正文

JavaScript基础提升【三】

目录

JavaScript构造函数

向JavaScript构造函数添加方法

new.target

JavaScript原型继承

在ES5中实现原型继承的标准方法

JavaScript对象属性

对象属性类型

数据属性

访问器属性

定义多个属性

JavaScript对象属性描述符

JavaScript可枚举属性   

JavaScript对象解构

设置默认值

解构空对象

嵌套对象解构

JavaScript可选链运算符

ES6中的对象字面量语法扩展

对象属性初始化简写

计算属性

其它


JavaScript构造函数

构造函数是一个普通的函数,遵循以下约定:

  • 构造函数的名称以大写字母开头,例如:Person、Document
  • 构造函数只能使用“new”运算符调用

以下示例定义了一个名为“Person”的构造函数

function Person(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;
}let person = new Person("John", "Doe");

new”运算符执行以下操作:

  • 创建一个新的空对象,并将其分配给this变量
  • 将参数John、Doe分配给this变量的firstName和lastName
  • 返回this

它等效于:

function Person(firstName, lastName) {const thisObject = {};thisObject.firstName = firstName;thisObject.lastName = lastName;return thisObject;
}let person = Person("John", "Doe");

向JavaScript构造函数添加方法

对象可能包含用于操作其数据的方法,同样使用this关键字向构造函数添加方法:

function Person(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;this.getFullName = function() {return this.firstName + " " + this.lastName;}
}let person = new Person("John", "Doe");console.log(person.getFullName()); // John Doe

但是这样有一个问题,如果你创建了非常多的Person实例,每个实例都有一个getFullName这样非常浪费内存空间,所以我们可以使用“原型”来解决问题,一个简单的原型如下所示:

function Person(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;
}// 使用prototype
Person.prototype.getFullName = function() {return this.firstName + " " + this.lastName;
}
// 或使用__proto__
let person = new Person("John", "Doe");
person.__proto__.getFullName = function() {return this.firstName + " " + this.lastName;
}
// 或使用getPrototypeOf
Object.getPrototypeOf(person).getFullName = function() {return this.firstName + " " + this.lastName;
}console.log(person.getFullName()); // John Doe

new.target

ES6标准新增new.target属性,如果构造函数不是被new关键字调用,而是当做普通函数调用,那么它返回undefined,同时函数也返回undefined。

function Person(firstName, lastName) {console.log(new.target); // undefinedthis.firstName = firstName;this.lastName = lastName;this.getFullName = function() {return this.firstName + ' ' + this.lastName;}
}const person = Person('John', 'Doe');
console.log(person); // undefined

利用这个特性,我们可以使语法更加灵活:

function Person(firstName, lastName) {if (!new.target) {return new Person(firstName, lastName);}this.firstName = firstName;this.lastName = lastName;this.getFullName = function() {return this.firstName + ' ' + this.lastName;}
}const person = Person('John', 'Doe');
console.log(person.getFullName()); // John Doe

JavaScript原型继承

假设定义了一个person对象

const person = {name: "John Doe",greet: function() {return `Hello, my name is ${this.name}`;}
}

person对象有一个属性和方法

  • name:一个属性,存储名字
  • greet:一个方法,打印招呼

默认情况下,JavaScript引擎会为person提供一个内置的Object()函数和一个匿名对象,可以使用Object.prototype来引用:

  • 圆圈代表函数,正方形代表对象

person对象与Object()函数prototype对象之间存在链接

相当于person对象是Object()函数的一个示例

此时再定义一个teacher对象,它有一个teach()方法:

const teacher = {teach: function(subject) {return "I can teach " + subject;}
}

它同样有Object.prototype原型:

此时person和teacher是兄弟的关系,彼此无法使用对方的方法,但是可以将teacher的原型设置为person:

const person = {name: "John Doe",greet: function() {return `Hello, my name is ${this.name}`;}
}
const teacher = {teach: function(subject) {return "I can teach " + subject;}
}
teacher.__proto__ = person;console.log(teacher.greet()); // Hello, my name is John Doe

在ES5中实现原型继承的标准方法

ES5提供了一种使用Object.create()方法来处理原型继承的标准方法

Object.create()方法创建一个新对象,并使用现有对象作为新对象的原型:

Object.create(proto, [propertiesObject])

Object.create()方法接收两个参数:

  • proto:用作新对象原型的对象
  • propertiesObject(可选):定义了新对象的附加属性
const person = {name: "John Doe",greet: function() {return `Hello, my name is ${this.name}`;}
}const teacher = Object.create(person, {teach: function () {return `${this.name} is now teaching.`;}
})console.log(teacher.greet()); // "Hello, my name is John Doe"

JavaScript对象属性

对象属性类型

JavaScript通过用两对方括号包围的内部属性来指定对象属性的特征(属性也有属性,有点绕)

对象有两种类型的属性:“数据属性”和“访问器属性

数据属性

数据属性包含一个用于数据值的单一位置。数据属性具有四个属性:

  • [[ Configurable ]]:确定是否可以通过delete运算符重新定义或删除属性
  • [[ Enumerable ]]:指定属性是否可以在“for...in”循环中返回
  • [[ Writable ]]:指定属性的值是否可以更改
  • [[ Value ]]:包含属性的实际值

默认情况下,[[ Configurable ]][[ Enumerable ]][[ Writable ]]属性对于直接在对象上定义的所有属性都设置为true[[ Value ]]属性的默认值为undefined

如果使用Object.defineProperty()方法给对象添加属性,那么[[ Configurable ]][[ Enumerable ]][[ Writable ]]的默认值都是false

Object.defineProperty()方法接收三个参数:

  • 一个对象
  • 对象的属性名称
  • 一个属性描述符对象,该对象具有四个属性:configurable、enumerable、writable、value
const test = {};Object.defineProperty(test, 'value', {configurable: false,enumerable: true,writable: false,value: 100
});console.log(test.value);
test.value = 200; // 错误,value属性是只读的
delete test.value; // 错误,value属性是不可配置的

如果一个属性的configurablefalse,那么他将不能被defineProperty配置:

Object.defineProperty(test, 'value', {configurable: false,enumerable: true,writable: false,value: 100
});
Object.defineProperty(test, 'value', {configurable: true,
}); // 错误,value属性是不可配置的

访问器属性

访问器属性有四个属性:

  • [[ Configurable ]]:控制属性是否可以配置
  • [[ Enumerable ]]:控制属性是否可以在for...in中被遍历
  • [[ Get ]]:尝试访问属性时,执行该函数
  • [[ Set ]]:尝试修改属性时,执行该函数

定义访问器属性,必须使用Object.defineProperty()方法:

const test = {firstName: 'John',lastName: 'Doe'
};Object.defineProperty(test, 'value', {get: function() {return this.firstName + ' ' + this.lastName;},set: function(value) {if (typeof value !== 'string') {throw new Error('Invalid value');}else {this.firstName = value.split(' ')[0];this.lastName = value.split(' ')[1];}}
})console.log(test.value); // John Doe
test.value = 'Jane Doe';
console.log(test.value); // Jane Doe
test.value = 123; 
console.log(test.value); // Invalid value
test.value = new String(123);
console.log(test.value); // Invalid value

定义多个属性

可以使用Object.defineProperties()方法在单个语句中定义多个属性:

const product = {};Object.defineProperties(product, {name: {value: 'Apple'},price: {writable: true,value: 100},getInfo: {get: function () {return `${this.name} ${this.price}`;}},setPrice: {set: function (newPrice) {this.price = newPrice;}}
})console.log(product.getInfo);
product.setPrice = 200;

在这里定义两个数据属性:“name”、“price”,两个访问器属性:“getInfo”、“setPrice

JavaScript对象属性描述符

Object.getOwnPropertyDescriptor()方法允许您获取属性的描述符对象,描述符对象包含四个属性:

  • [[ Configurable ]]:确定是否可以通过delete运算符重新定义或删除属性
  • [[ Enumerable ]]:指定属性是否可以在“for...in”循环中返回
  • [[ Writable ]]:指定属性的值是否可以更改
  • [[ Value ]]:包含属性的实际值

Object.getOwnPropertyDescriptor()接收两个参数:“对象名”、“属性名”

const person = {firstName: 'John',lastName: 'Doe'
};const descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log(descriptor); // { value: 'John', writable: true, enumerable: true, configurable: true }

JavaScript可枚举属性   

可枚举属性可以使用for...in循环或Objects.keys()方法进行迭代

可枚举属性的enumerable为true时才可以迭代

ES6提供了一个方法:propertyIsEnumerable(),用于确定属性是否可枚举

如果属性可枚举返回true,否则返回false

const person = {firstName:"John",lastName:"Doe",
};person.age = 20;Object.defineProperty(person, 'ssn', {enumerable: false,value: '123-45-6789'
})console.log(person.propertyIsEnumerable('ssn')); // false
console.log(person.propertyIsEnumerable('firstName')); // true
console.log(person.propertyIsEnumerable('lastName')); // true
console.log(person.propertyIsEnumerable('age')); // true

JavaScript对象解构

对象解构是将属性从另一个对象分配给变量的便捷语法

const person = {firstName:"John",lastName:"Doe",
};const { firstName: fName, lastName: lName } = person;

冒号(:)之前的标识符是对象的属性,冒号之后的标识符是对象

如果变量与对象的属性同名,可以用下面的方式使代码更简洁:

const person = {firstName:"John",lastName:"Doe",
};const { firstName, lastName} = person;
console.log(firstName); // John
console.log(lastName);  // Doe

但是使用对象解构将不存在的属性分配给变量时,该变量将被设置为“undefined

let { firstName, lastName, middleName } = person;
console.log(middleName); // undefined

设置默认值

当对象的属性不存在时,可以将默认值分配给变量:

let person = {firstName: 'John',lastName: 'Doe',currentAge: 28
};let { firstName, lastName, middleName = '', currentAge: age = 18 } = person;console.log(middleName); // ''
console.log(age); // 28

解构空对象

有些时候,解构的函数返回值可能返回一个空值,这个时候直接解构是报错的:

function getPerson() {return null;
}
let { firstName, lastName } = getPerson();console.log(firstName, lastName); // undefined undefined

为了避免这种情况,可以使用OR运算符(||)将null对象回退到一个空对象

let { firstName, lastName } = getPerson() || {};

此时firstNamelastName将为undefined

嵌套对象解构

嵌套对象解构只需要在对应位置放置对应变量即可:

let employee = {id: 1001,name: {firstName: 'John',lastName: 'Doe'}
};
let {name: {firstName,lastName}
} = employee;console.log(firstName); // John
console.log(lastName); // Doe

JavaScript可选链运算符

可选链运算符(?.)就像一个访问对象系列中嵌套属性的快捷方式。这样就无需检查链中每个步骤是否为空(nullundefined),而是可以使用链运算符?.直接访问所需的属性

如果链的任何部分为空,可选链运算符(?.)将立即停止并返回undefined运算符为结果。它可以避免您为链中每个步骤编写额外的检查。

function getUser(id) {if(id <= 0) {return null;}return {id: id,username: 'admin',profile: {avatar: '/avatar.png',language: 'English'}}
}// 之前的做法
let user = getUser(2);
let profile = user && user.profile;
// 可选链运算符
let user = getUser(2);
let profile = user ?. profile;

ES6中的对象字面量语法扩展

对象属性初始化简写

在ES6之前,对象字面量是:“键:值”对的集合:

function createMachine(name, status) {return {name: name,status: status};
}

name、status在对象中出现了两次,这样写起来很冗余,在ES6之后可以:

function createMachine(name, status) {return {name,status};
}

计算属性

一个对象的属性名如果是一个字符串,就必须使用[]方括号调用:

let name = 'machine name';
let machine = {[name]: 'server','machine hours': 10000
};console.log(machine[name]); // server
console.log(machine['machine hours']); // 10000

其它

更多JavaScript学习可以参考我的专栏:JavaScript_是洋洋a的博客-CSDN博客

http://www.dtcms.com/a/554780.html

相关文章:

  • 百度网盘 做网站图床美区能和国区家庭共享吗
  • 基于3DGIS+BIM的智慧园区运维平台价值分享
  • atsec出席2025 PCI社区会议
  • 白云区建材网站建设推广wordpress换了ip
  • 旌阳区黄河开发建设网站建设工程施工司法解释
  • 外包网站设计哪家好怎样建立网站平台
  • 海南省工程建设定额网站网站建设的SOWT分析
  • 第1讲:彻底解决C++中资源泄露
  • CentOS 7上运行C程序
  • 网站建设有什么证.net程序员网站开发工程师
  • 安信可(Ai-Thinker)WiFi系列模块全解析:选型指南与应用洞察
  • 科技建站网站源码黄金网站app视频播放画质选择
  • 品牌网站设计图片企业软件管家
  • NetSuite 如何删除未生成的Memorized Transaction?
  • 秦皇岛优化网站排名邹城网站建设
  • 扁平化网站导航ui模板电子商务网站建设与管理理解
  • 有什么网站可以做毕业影像页面设计源代码
  • 金泽通 打造数字金融与商业融合新模式
  • 【算法专题训练】29、树的深度优先遍历
  • Rust + WebAssembly 实现多人在线共享白板:从设计到性能验证
  • 电脑什么网站可以做长图攻略阳光家园广州网站
  • 新网站建设平台上海做网站运维的公司
  • javan
  • 在VSCode+Guider基础上 运行Button圆角demo
  • 【更新至 91 个】分子动力学模拟 + 数据处理程序
  • LIBTORCH 再配置总结
  • element-ui源码阅读-样式
  • 重生归来,我要成功 Python 高手--day31 线性回归
  • 网站开发python和c 哪个好住房和城乡建设部科技发展促进中心网站
  • 黑彩网站建设立即优化在哪里