- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
程序就是对现实世界的抽象,一个事物抽象到程序中后就变成了对象,在程序的世界中,一切皆对象 。
面向对象的编程指,程序中的所有操作都是通过对象来完成 。
做任何事情之前都需要先找到它的对象,然后通过对象来完成各种操作 。
一个事物通常由两部分组成:数据和功能 。
一个对象由两部分组成:属性和方法 。
事物的数据到了对象中,体现为属性 。
事物的功能到了对象中,体现为方法 。
const user = { // 添加属性 name:"seven", age:18, weight:100, // 添加方法 get_info(){ console.log(`姓名:${this.name},年龄:${this.age},体重:${this.weight}`) }, set_age(age){ this.age = age } }
使用Object创建对象
通过class创建对象 。
calss 类名{}
、const 类名 = claskk{}
new 类名()
class User {
}
// User() : 构造函数
const u1 = new User()
console.log(u1 instanceof User) // true
class User {
name = "mickey" // 实例属性,只能通过实例访问 const u = new User() u.name
static age = 18 // 静态属性(类属性),只能通过类去访问,User.age
}
// 使用new关键字调用构造函数User创建一个新的对象实例,即实例化对象
const user = new User()
console.log(user.name) // mickey
user.city = "Beijing"
console.log(user.city) // Beijing
class User {
name = "mickey"
static age = 18
// 添加方法-实例方法(不建议使用)
sayHello = function (){
console.log("hello world")
}
// 实例方法,通过实例.方法名调用(建议使用)
printName(){
console.log(this.name) // 实例方法中this就是当前实例
}
// 静态方法(类方法),通过类.方法名调用
static test(){
console.log(this.age) // 静态方法中this指向的是当前类
}
}
const user = new User()
user.sayHello()
user.printName()
User.test()
class User {
// 在类中直接指定实例属性的值时,创建的所有对象属性都是这个值
name = "mickey"
}
class User {
// 在类中可以添加一个特殊的方法constructor
// 该方法我们称为构造函数(构造方法)
// 构造函数会在我们调用类创建对象时执行
// 即该类实例化的时候会直接执行
constructor(name,age) {
// 可以在构造函数给实例属性赋值,构造函数中this表示当前所创建的对象
this.name = name
this.age = age
}
}
const u1 = new User("l",18)
console.log(u1) // {name: 'l', age: 18}
const u2 = new User("q",28)
console.log(u2) // {name: 'q', age: 28}
面向对象三大特性:封装、继承、多态 。
数据安全 。
对象就是一个用来存储不同属性的容器 。
对象不仅存储属性,还要负责数据的安全 。
直接添加到对象中的属性,并不安全,因为它们可以被任意的修改 。
私有化数据 。
#name
提供setter和getter方法来开放对数据的操作 。
模块化与可维护性 。
封装可以使代码更加模块化,将相关的数据和功能封装在一个对象或模块中。这样可以使代码结构更加清晰,易于理解和维护 。
可以提供统一的接口来访问和操作数据,确保外部代码以一致的方式与对象进行交互.
例如,一个封装良好的对象可以提供一组方法来执行特定的操作,外部代码不需要了解内部的实现细节,只需要调用这些方法即可 。
class User {
// 私有属性必须先声明
// 声明赋值的私有属性
#name = "q"
// 声明未赋值的私有属性
#age
constructor(age) {
this.#age = age
}
getAge(){
return this.#age
}
getName() {
return this.#name // 获取私有属性name
}
setName(name) {
if (name != null){
this.#name = name // 修改私有属性name
}
}
}
const user = new User(67)
console.log(user.getName())
console.log(user.getAge())
user.setName()
通过getter和setter获取和设置私有属性值 。
class User {
#name
// getter 获取name属性值
get name(){
return this.#name
}
// setter 设置name属性值
set name(name){
this.#name = name
}
}
const user = new User()
user.name = "l"
console.log(user.name)
在JS中不会检查参数的类型,所以这就意味着任何数据都可以作为参数传递 。
要调用某个函数,无需指定的类型,只要对象满足某些条件即可 。
多态为我们提供了灵活性 。
class User{
constructor(name) {
this.name = name
}
}
const u1 = new User("l")
const u2 = new User("q")
function sayHello(obj){
console.log("hello ",obj.name)
}
sayHello(u1)
sayHello(u2)
可以通过extends关键来完成继承 。
class User{
constructor(name) {
this.name = name
}
getInfo() {
console.log(this.name)
}
}
// 使用extends关键字 Admin继承User类
class Admin extends User{
}
const a = new Admin("l")
a.getInfo()
通过继承可以在不修改一个类的情况下对其进行扩展 。
面向对象OCP开闭原则:程序应该对修改关闭,对扩展开放 。
// 使用extends关键字 Admin继承User类
// 在子类中,可以通过创建同名方法来重写父类的方法
class Admin extends User{
// 重写构造函数
constructor(name) {
// 重写构造函数时,构造函数的第一行代码必须为super()
super(name);
this.name = name
}
// 重写getInfo方法
getInfo(){
super.getInfo() // 通过super调用父类的getInfo方法
console.log("名字是:",this.name)
}
}
const a = new Admin("l")
a.getInfo()
对象中存储属性的区域实际有两个:
对象自身 。
- 直接通过对象所添加的属性,位于对象自身中
- 在类中通过key=value的形式添加属性、方法,位于对象自身中
原型对象(prototype) 。
对象中还有一些内容,会存储到其他的对象里 。
对象中会有一个属性用来存储原型对象,这个属性叫做__proto__ 。
原型对象也负责为对象存储属性 。
我们访问对象中的属性时,会优先访问对象自身的属性, 。
对象自身不包含该属性时,才会去原型对象中寻找 。
会添加到原型对象中的情况:
在类中通过xxx(){}方式添加的方法,位于原型中 。
主动向原型中添加的属性或方法 。
class User {
name = "l" // 存储对象自身
get = function (){} // 存储对象自身
set(){} // 存储原型对象
}
// 对象本身
const user = new User()
// 访问原型对象
console.log(user.__proto__)
// 访问原型对象
console.log(Object.getPrototypeOf(user))
原型对象中的数据:
1. 对象中的数据(属性、方法等),比如User.set()方法
2. constructor (对象的构造函数)
原型对象也有对应的原型对象,构成一条原型链,根据对象的复杂程度不同,原型链的长度也不同 。
// 访问user对象的原型对象的原型对象
console.log(user.__proto__.__proto__)
原型链:
// 所以的同类型对象的原型对象都是同一个,也就意味着同类型对象的原型链是一样的
var u1 = new User()
var u2 = new User()
console.log(u1.__proto__ === u2.__proto__) // true
所有同类型对象的原型链都是一个,原型就相当于是一个公共的区域,只需要创建一个可以被所有该类实例访问 。
在对象中有些值是对象独有的,比如属性,每个对象都应该有自己值,有些值对于每个对象都是一样的,像各种方法,对于一样的值没有必要重复创建,比如set()方法,在原型中,new100个对象只会创建1次,而不是创建100次 。
// 对于某些是每个对象独立的方法,可以使用x=y的方式存储在对象真实
class User {
get = function (){} // 存储对象自身,每个对象创建一个
set(){} // 存储原型对象,原型链共用,多个对象不会重复创建
}
// 继承User
class Admin extends User{
}
const a = new Admin()
// user实例 --> object --> Object原型 --> null
console.log(a.__proto__.__proto__.__proto__.__proto__)
//Object.create()是 JavaScript 中用于创建一个新对象的方法,这个新对象的原型可以指定为某个已有的对象
/*
Object.create(proto, [propertiesObject])
proto:新创建对象的原型对象,可以是一个已有的对象,如果null,则新创建的对象没有原型,不会继承任何属性和方法
propertiesObject(可选):包含属性描述符的对象,用于定义新对象自身的属性
当将 proto 参数设置为 null 时,可以创建一个没有原型的对象。这种对象通常用于存储临时数据或实现特定的算法,以避免意外地访问到原型链上的属性
*/
const parent = {
sayHello() {
console.log('Hello from parent')
}
}
const child = Object.create(parent)
child.sayHello()
// 创建一个没有原型的新对象,定义了一个名为 name 的属性,属性值为 john,属性全保险是可写、可枚举、可配置
const newObject = Object.create(null, {
name: {
value: 'John',
writable: true,
enumerable: true,
configurable: true
}
});
一般情况下,不需要修改原型对象 。
/*
不建议通过类的实例去修改原型:因为会通过一个对象影响所有同类对象
*/
const a = new Admin()
const a1 = new Admin()
const a2 = new Admin()
// a、a1、a2对象的set方法都会被修改
a.__proto__.set = () => {}
a2.__proto__ = new Base() // 不会影响其他对象,相当于是给a2对象赋值了一个新的原型对象
通过prototype修改原型对象 。
User.proptotype // 访问User实例的原型对象
User.prototype.get = () => {} // 给所有实例添加一个get方法
原型一般不需要修改,如果要修改通过类.prototype去修改 。
// instanceof 用来检查一个对象是否是一个类的实例
// 检查的是对象的原型链上是否有该类实例只要原型链上有该类实例,就会返回true
// Object是所有对象的原型,所以任何和对象和Object进行instanceof运算都会返回true
class User {
}
// 继承User
class Admin extends User{
name = "l"
get(){}
set = function (){}
}
const admin = new Admin()
console.log(admin instanceof Admin) // true
console.log(admin instanceof User) // true
console.log(admin instanceof Object) // true
// in用来检查一个对象的自身是否含有某个属性
// 使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回true
console.log("get" in admin) // true
// 对象.hasOwnProperty检查一个对象的自身是否包含某个属性(不推荐使用)
// hasOwnProperty是在Object原型中的一个方法
console.log(admin.hasOwnProperty("name")) // true
console.log(admin.hasOwnProperty("set")) // true
console.log(admin.hasOwnProperty("get")) // false
// Object.hasOwn(对象,属性名) 用来检查一个对象的自身是否含有某个属性(推荐使用)
console.log(Object.hasOwn(admin,"name")) // true
console.log(Object.hasOwn(admin,"set")) // true
console.log(Object.hasOwn(admin,"get")) // false
早期js中通过函数定义类,如果直接调用就是一个普通函数,通过new调用就是一个构造函数 。
function User(name){
// 在构造函数中,this表示新建的对象
this.name = name
}
// 向原型中添加属性(方法)
User.prototype.get = function(){}
// 静态属性
User.staicName = "a"
// 静态方法
User.staticGet = function(){}
User() // 普通函数
const user = new User() // 构造函数
通过旧的方式创建类,方法属性比较分散,可以将其放在一个立即执行函数里面 。
var User = (function () {
function User(name){
// 在构造函数中,this表示新建的对象
this.name = name
}
// 向原型中添加属性(方法)
User.prototype.get = function () {
}
// 静态属性
User.staicName = "a"
// 静态方法
User.staticGet = function () {
}
const user = new User() // 构造函数
// 返回User
return User
}
)()
const u = new User("l")
console.log(u.name)
// 旧类继承
var User = (function () {
function User() {
}
return User
})()
var Admin = (function () {
function Admin() {
}
// 继承User,将User对象赋值给Admin的原型
Admin.prototype = new User()
return Admin
})()
当使用new 去调用一个函数时,这个函数将会作为构造函数调用 。
- 创建一个普通的JS对象(Object对象 {}), 称其为新对象
- 将构造函数的prototype属性设置为新对象的原型
- 使用实参来执行构造函数,并且将新对象设置为函数中的this
- 如果构造函数返回的是一个非原始值,则该值会作为new运算的返回值返回(千万不要这么做)
如果构造函数的返回值是一个原始值或者没有指定返回值,则新的对象将会作为返回值返回
通常不会为构造函数指定返回值
// 1.创建一个普通的JS对象
var newInstance = {}
// 2.构造函数的prototype属性设置为新对象的原型
newInstance.__proto__ = NewObject.prototype
// 3.使用实参来执行构造函数,并且将新对象设置为函数中的this
constructor() {
// 4.如果构造函数返回的是一个非原始值,则该值会作为new运算的返回值返回(千万不要这么做)
// 如果构造函数的返回值是一个原始值或者没有指定返回值,则新的对象将会作为返回值返回
// 通常不会为构造函数指定返回值
}
对象的分类:
内建对象 。
- 由ES标准所定义的对象
- Object Function String Number ....
宿主对象 。
- 由浏览器提供的对象
- BOM、DOM
自定义对象 。
- 由开发人员自己创建的对象
最后此篇关于Js面向对象的文章就讲到这里了,如果你想了解更多关于Js面向对象的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在学习构建单页应用程序 (SPA) 所需的所有技术。总而言之,我想将我的应用程序实现为单独的层,其中前端仅使用 API Web 服务(json 通过 socket.io)与后端通信。前端基本上是
当我看到存储在我的数据库中的日期时。 这是 正常 。日期和时间就是这样。 但是当我运行 get 请求来获取数据时。 此格式与存储在数据库 中的格式不同。为什么会发生这种情况? 最佳答案 我认为您可以将
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在尝试使用backbone.js 实现一些代码 和 hogan.js (http://twitter.github.com/hogan.js/) Hogan.js was developed ag
我正在使用 Backbone.js、Node.js 和 Express.js 制作一个 Web 应用程序,并且想要添加用户功能(登录、注销、配置文件、显示内容与该用户相关)。我打算使用 Passpor
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我尝试在 NodeJS 中加载数据,然后将其传递给 ExpressJS 以在浏览器中呈现 d3 图表。 我知道我可以通过这种方式加载数据 - https://github.com/mbostock/q
在 node.js 中,我似乎遇到了相同的 3 个文件名来描述应用程序的主要入口点: 使用 express-generator 包时,会创建一个 app.js 文件作为生成应用的主要入口点。 通过 n
最近,我有机会观看了 john papa 关于构建单页应用程序的精彩类(class)。我会喜欢的。它涉及服务器端和客户端应用程序的方方面面。 我更喜欢客户端。在他的实现过程中,papa先生在客户端有类
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我是一个图形新手,需要帮助了解各种 javascript 2D 库的功能。 . . 我从 Pixi.js 中得到了什么,而我没有从 Konva 等基于 Canvas 的库中得到什么? 我从 Konva
我正在尝试将一些 LESS 代码(通过 ember-cli-less)构建到 CSS 文件中。 1) https://almsaeedstudio.com/ AdminLTE LESS 文件2) Bo
尝试查看 Express Passport 中所有登录用户的所有 session ,并希望能够查看当前登录的用户。最好和最快的方法是什么? 我在想也许我可以在登录时执行此操作并将用户模型数据库“在线”
我有一个 React 应用程序,但我需要在组件加载完成后运行一些客户端 js。一旦渲染函数完成并加载,运行与 DOM 交互的 js 的最佳方式是什么,例如 $('div').mixItUp() 。对
请告诉我如何使用bodyparser.raw()将文件上传到express.js服务器 客户端 // ... onFilePicked(file) { const url = 'upload/a
我正在尝试从 Grunt 迁移到 Gulp。这个项目在 Grunt 下运行得很好,所以我一定是在 Gulp 中做错了什么。 除脚本外,所有其他任务均有效。我现在厌倦了添加和注释部分。 我不断收到与意外
我正在尝试更改我的网站名称。找不到可以设置标题或应用程序名称的位置。 最佳答案 您可以在 config/ 目录中创建任何文件,例如 config/app.js 包含如下内容: module.expor
经过多年的服务器端 PHP/MySQL 开发,我正在尝试探索用于构建现代 Web 应用程序的新技术。 我正在尝试对所有 JavaScript 内容进行排序,如果我理解得很好,一个有效的解决方案可以是服
我是 Nodejs 的新手。我在 route 目录中有一个 app.js 和一个 index.js。我有一个 app.use(multer....)。我还定义了 app.post('filter-re
我正在使用 angular-seed用于构建我的应用程序的模板。最初,我将所有 JavaScript 代码放入一个文件 main.js。该文件包含我的模块声明、 Controller 、指令、过滤器和
我是一名优秀的程序员,十分优秀!