创建对象
<script>
// 方法一:new Object()
const obj1 = new Object()
obj1.name = 'Jack'
console.log(obj1);
// 方法二:字面量
const obj2 = { name: 'Jack' }
console.log(obj2);
// 方法三:利用构造函数创建对象
function Pig(name, age) {
this.name = name
this.age = age
}
console.log(new Pig('佩奇', 6));
</script>
实例与静态成员
实例成员:
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员
实例成员包含:实例属性和实例方法
静态成员:
构造函数的属性和方法被称为静态成员
静态成员包含:静态属性和静态方法
说明:
1.静态成员只能构造函数来访问
2.静态方法中的this指向构造函数
<script>
// 构造函数
function Person(name, age) {
// 实例属性
this.name = name
this.age = age
// 实例方法
this.sayHi = function () {
console.log('Hi');
}
}
// 静态属性
Person.eyes = 2
Person.arms = 2
// 静态方法
Person.walk = function () {
console.log('人都会走路');
// 下面的 this 指向 Person
console.log(this.eyes);
}
</script>
内置构造函数
Object
<script>
const obj1 = { name: 'Jack', age: 30 }
// 获取所有的属性名
console.log(Object.keys(obj1)); // 返回数组 ['name', 'age']
// 获取所有的属性
console.log(Object.assign(obj1)); // 返回数组 ['Jack', 30]
// 追加对象属性
const obj2 = {gender:'男'}
Object.assign(obj2, obj1) // 将obj1的属性追加到obj2
console.log(obj2);
</script>
Array
- reduce() 方法
<script>
// arr.reduce(function (上一次值, 当前值){...}, 初始值)
arr = [1, 5, 8]
// 1.没有初始值
const total_1 = arr.reduce(function (prev, current) {
return prev + current
}) // 执行过程:1 + 5 => 6 + 8
// 2.有初始值
const total_2 = arr.reduce(function (prev, current) {
return prev + current
}, 10) // 执行过程:10 + 1 => 11 + 5 => 16 + 8 => 24
// 3.箭头函数的形式
const total_3 = arr.reduce((prev, current) => prev + current, 10)
console.log(total_3); // 24
</script>
- 其他方法:点击查询更多方法 |MDN
String
- split() 方法
<script>
// split 把字符串转换为数组,刚好与join()相反
const str = 'green|red'
const arr = str.split('|')
console.log(arr); // ['green', 'red']
</script>
- substring() 方法
<script>
// 字符串的截取
const str = '我一直都热爱这份事业'
console.log(str.substring(1, 3)); // 输出结果: 一直
</script>
- startsWith() 方法
<script>
// 判断字符串是否以xxx开头
str = 'Hello World'
alert(str.startsWith('He')) // true
</script>
- 更多方法:点击查询更多方法 | MDN
Number
- toFixed() 设置保留小数位的长度
<script>
// 数值类型
const price = 12.345
// 保留两位小数 四舍五入
console.log(price.toFixed(2)); // 12.35
</script>
原型
原型对象(prototype)
基本概念
- 构造函数通过原型分配的函数是所有对象所共享的
- JavaScript规定,每一个构造函数都有一个 prototype 属性
- 这个属性,指向另一个对象,所以我们也称之为原型对象
- 这个对象可以挂载函数,对象实例化不会多次创建在原型对象上
- 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法
- 构造函数和原型对象中的 this 都指向实例化的对象
具体内容
<script>
// 公共的属性写到构造函数里面(每个对象自己都有一份,浪费内存)
function People(name, age) {
this.name = name
this.age = age
// this.sing = function() {
// console.log('唱歌');
// }
}
// 公共的方法写到"原型对象"身上(所有对象共享,节约内存)
People.prototype.sing = function () {
console.log('唱歌');
}
// 实例化对象
const obj1 = new People('Jack', 30)
const obj2 = new People('Peter', 25)
// 调用方法
obj1.sing()
obj2.sing()
console.log(obj1.sing === obj2.sing); // true
</script>
案例演示
- 给数组自定义的扩展一个"求和"的方法
<script>
// 数组
const arr = [1, 2, 3]
// 自定义方法
Array.prototype.sum = function () {
return this.reduce((prev, current) => prev + current, 0)
}
// 调用该方法
console.log(arr.sum());
</script>
- 给数组自定义的扩展一个"最大值"的方法
<script>
// 数组
const arr = [1, 2, 3]
// 自定义方法
Array.prototype.max = function () {
return Math.max(...this)
}
// 调用该方法
console.log(arr.max());
</script>
- 给数组自定义的扩展一个"最小值"的方法
<script>
// 数组
const arr = [1, 2, 3]
// 自定义方法
Array.prototype.min = function () {
return Math.min(...this)
}
// 调用该方法
console.log(arr.min());
</script>
constructor 属性
基本概念
- 每个"原型对象"里面都有一个 constructor 属性(constructor 构造函数)
- 作用:这个属性指向"该原型对象的构造函数"
<script>
function People() {
// ...
}
console.log(People.prototype.constructor === People); // true
</script>
具体演示
当我们给"原型对象"一个一个的去添加"功能函数"时,会不会觉得非常的麻烦?下面的方法,能够快速的解决这个问题。
<script>
// 构造函数
function People() {
// ...
}
// People.prototype.sing = function () {
// console.log('唱歌');
// }
// People.prototype.dance = function () {
// console.log('跳舞');
// }
// 输出
console.log(People.prototype)
// 输出内容:
// constructor: ƒ People()
// 在修改原型对象的时候,除了添加你需要的函数功能
// 请记得!还要添加"constructor:构造函数"
// 以此实现"让它指回原来的构造函数"的目的
People.prototype = {
constructor: People,
sing: function () { console.log('唱歌'); },
dance: function () { console.log('跳舞'); }
}
// 输出
console.log(People.prototype)
// 输出内容:
// constructor: ƒ People()
// dance: ƒ ()
// sing: ƒ ()
</script>
对象原型(__proto__
)
思考引入
问题:
- “构造函数"可以创建"实例对象”,“构造函数"还有一个"原型对象”
- 一些公共的属性或者方法,可以放到"原型对象"上
- 但是为什么"实例对象"可以访问"原型对象"里面的属性和方法呢?
答案:
- "实例对象"都会有一个
__proto__
属性 - 这个属性,指向构造函数的"原型对象"
__proto__
属性,我们称之为"对象原型"
注意事项
__proto__
是 JS 非标准属性,用来表明"当前实例对象"指向哪个"原型对象"[[prototype]]
和__proto__
意义相同__proto__
里面也有一个constructor
属性,指向创建该实例对象的"构造函数"
<script>
// 构造函数
function People() { }
// 实例对象
const obj = new People()
// 校验
console.log(obj.__proto__.constructor === People); // true
</script>
原型继承
<script>
// 构造函数(人)
function People() {
this.eyes = 2
this.head = 1
}
// 构造函数(Woman)
function Woman() {
// ...
}
// Woman 通过原型对象prototype来继承Person
Woman.prototype = new People()
// 因为使用对象的赋值操作,所以prototype原来的constructor没了,我们需要手动添加回去
Woman.prototype.constructor = Woman
// 女人独有的能力
Woman.prototype.beauty = function () {
console.log('美丽动人')
}
// 构造函数(Man)
function Man() {
// ...
}
// 同上
Man.prototype = new People()
Man.prototype.constructor = Man
// 男人独有的能力
Man.prototype.handsome = function () {
console.log('英俊潇洒')
}
// 创建对象
const obj1 = new Woman()
const obj2 = new Man()
// 输出
console.log(obj1.beauty())
console.log(obj2.handsome())
console.log(Woman.prototype)
console.log(Man.prototype)
</script>
原型链
基本认识
- 基于原型对象的继承,使得不同构造函数的原型对象关联在一起
- 并且这种关联的关系是一种链状的结构
- 我们将这种
原型对象的链状结构关系
称为原型链
查找规则
- 当访问一个对象的属性或方法时
- 首先查找这个对象"自身"有没有该属性
- 如果没有,就查找它的原型(也就是
__proto__
指向的prototype原型对象
) - 如果还没有,就继续向上查找
- 依此类推,直到找到 Object 为止
__proto__
对象原型的意义就在于,为对象成员查找机制提供一个方向,或者说一条路线- 可以使用 instanceof 运算符,去检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
<script>
function Person() { }
const obj = new Person()
console.log(obj instanceof Person) // true
console.log(obj instanceof Object) // true
console.log(obj instanceof Array) // false
</script>
面向对象编程案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.btn {
text-align: center;
}
.modal {
margin: 200px auto;
padding: 10px;
width: 400px;
height: 150px;
box-shadow: 5px 2px 10px 2px rgba(0, 0, 0, 0.5);
border-radius: 10px
}
.modal .header i {
margin-left: 300px;
}
.modal .body {
margin: 50px 0;
text-align: center;
}
</style>
</head>
<body>
<div class="btn">
<button id="delete">注册</button>
<button id="login">登录</button>
</div>
<script>
// 1. 完成Modal构造函数的封装
function Modal(title = '', message = '') {
// 创建modalm=模态框盒子
// 1.1 创建div标签
this.modalBox = document.createElement('div')
// 1.2 给div标签添加类名为modal
this.modalBox.className = 'modal'
// 1.3 modal盒子内部填充2个div标签,并且修改文字内容
this.modalBox.innerHTML = `
<div class="header">${title}<i>x</i></div>
<div class="body">${message}</div>
`
}
// 2. 给构造函数的原型对象挂载open方法
Modal.prototype.open = function () {
// 先来判断页面中是否有modal盒子,如果有先删除,没有就添加
const box = document.querySelector('.modal')
box && box.remove()
document.body.append(this.modalBox)
this.modalBox.querySelector('i').addEventListener('click', () => {
this.close() // 这个this指向实例对象
})
}
// 3. 给构造函数的原型对象挂载close方法
Modal.prototype.close = function () {
this.modalBox.remove()
}
// 点击注册按钮
document.querySelector('#delete').addEventListener('click', () => {
const obj = new Modal('温馨提示', '您还没有登录呢')
obj.open()
})
// 点击登录按钮
document.querySelector('#login').addEventListener('click', () => {
const obj = new Modal('友情提示', '您还没有注册呢')
obj.open()
})
</script>
</body>
</html>