-
构造函数 本质 其实也是一个函数
- 作用 用来创建对象
- 以前见过构造函数
Set 构造函数
Array 构造函数
Object
String
Number
Boolean
Date只要它被new 它 就是构造函数
Person 构造函数 首字母是大写(规范)
per 被new出来的对象 !!!
<script>
function Person() {}
// person 就是一个构造函数 被new
const per = new Person();
</script>
- 每一个构造函数中 都存在 有一个 魔鬼 this
构造函数 默认情况下 就是返回了 this
this 等于你所new出来的实例 per
只要给构造函数中的this 添加 属性或者方法
那么 实例 自然拥有对应的属性和方法
<script>
function Person() {
this.username = '悟空'; // per也增加了一个属性
this.add=()=>{};
this.clear=()=>{};
}
const per = new Person();
per.username = '悟空';
const per2 = new Person();
console.log(per);
console.log(per2);
</script>
构造函数-弊端
<script>
function Person() {
this.say = function () {};
}
const p1 = new Person();
const p2 = new Person();
console.log(p1 === p2); // 两个对象的比较 内存地址 false
console.log(p1.say === p2.say);// false 两个函数 存放在不同地址中
// const s1 = new Set();
// const s2 = new Set();
// console.log(s1 === s2);// false
// console.log(s1.add === s2.add); // true
// s1 和 s2 共享一个方法
// p1 和 p2 没有共享一个
</script>
对象在堆中情况


1.值类型 是存在 栈空间 适合存放 固定大小的数据
2. 引用类型(对象、数组、函数) 存在 堆空间 适合存放大小不固定的数据
3. new了两个对象的时候, 两个对象的内存地址 不相等
4. 我们希望 两个对象的方法 内存地址是相等!!!
5. 在构造函数中 当我们定义方法的时候 一般都不会只在在 构造函数中写死
让我们方法 都指向外部 单独声明的方法 多个实例去共享方法!!!
<script>
const obj1 = { username: '八戒' };
const obj2 = { username: '八戒' };
// console.log(obj1===obj2);// false 内存中的地址
const obj3 = obj2;
// console.log(obj3 === obj2); // true
obj3.username="悟空";
console.log(obj2);
</script>
<script>
function say() {
console.log('外部单独的say方法');
}
function Person() {
this.say = say;
}
const p1 = new Person();
const p2 = new Person();
console.log(p1 === p2); // false
console.log(p1.say === p2.say);// true
const obj1={username:"悟空"};
const obj2={username:"悟空"};
const obj3=obj2;
obj3.username="八戒";
console.log(obj2);
</script>
构造函数的基本使用
1. 构造函数的时候 属性 分成了两种
1. 函数类型的属性
一般都是写在外部!!!
2. 非函数类型的属性
一般是写在内部!!!
<script>
// 构造函数的方式 创建一个对象
// 姓名 属性
// 说出自己的姓名 方法
function say() {
console.log('这个是Person的一个方法', this.name);
}
function fly() {
console.log(this.name, '要起飞');
}
function Person(name, height) {
this.name = name;
this.height = height;
this.say = say;
this.fly = fly;
}
const p1 = new Person('八戒', 150);
// p1.say();
p1.fly();
</script>
构造函数使用演示
<script>
/*
1 有一个构造函数 Person
2 有数字类型的属性 发量 hair =100
3 有行为 decrease 减少 方法
发量 - 1
4 按钮 每点击一次 发量减少一根
*/
function decrease() {
this.hair--;
}
function Person() {
this.hair = 100;
this.decrease = decrease;
}
const btn = document.querySelector('button');
const p1 = new Person();
btn.addEventListener('click', function () {
// 每点击一次按钮 new一个对象
p1.decrease();
console.log(p1.hair);
});
</script>
构造函数+原型
-
原型 本质是一个对象 在我们创建构造函数的时候就拥有
2.在原型上添加的一些方法,可以直接被 实例所使用和共享- 可以这么理解 构造函数=父亲 实例=孩子 原型=DNA
- 使用面向对象的方式来创建对象
- 构造函数内部 来定义 非函数类型的属性 如 姓名 身高 肤色 性别
- 原型来定义 函数类型的属性 函数
<script>
// 构造函数 + 原型 搭配来使用
// 原型 本质 是一个对象
// 当我们在创建一个 构造函数的时候 原型 被创建
// 如果我们在原型对象上 增加一个属性或者方法 那么实例 拥有所增加的方法
// 原型 就是 DNA 构造函数 父亲 实例 孩子
// function Person() {
// this.b = function () {};
// }
// // 访问原型
// // console.log(Person.prototype);
// Person.prototype.a = function () {
// console.log('这个是a方法');
// };
// const p1 = new Person();
// // console.log(p1);
// p1.a();
// function Obj() {
// }
// Obj.prototype.a=function(){
// }
function Person() {
this.hair = 100;
// this.decrease = decrease;
}
Person.prototype.decrease = function () {
this.hair--;
};
</script>
案例 - 普通写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>17-课堂案例.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
img {
transition: 2s;
}
.scale {
transform: scale(2);
}
</style>
</head>
<body>
<button>放大</button>
<img src="./images/1.png" alt="" />
<script>
/*
1 静态结构
2 给按钮绑定点击事件
3 事件触发
1 获取图片的dom元素
2 添加一个class
4 面向过程写法
*/
const button = document.querySelector('button');
const img = document.querySelector('img');
button.addEventListener('click', function () {
img.classList.add('scale');
});
</script>
</body>
</html>
面向对象写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>index.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<button> 大</button>
<script>
function MyImg(src) {
// body标签上能出现一张图片
const img = document.createElement('img');
img.style.transition = '2s';
// 设置 图片地址
img.src = src;
// 在body标签上看见这一张图片
document.body.append(img);
this.abc = img;
}
// 原型上写一写函数
MyImg.prototype.scale = function (num) {
// 获取到 构造函数中 创建的 img dom元素 - 提前把img dom 添加到 this的属性中
this.abc.style.transform = `scale(${num})`;
};
const myImg = new MyImg('./images/1.png'); // body标签上能出现一张图片
const myImg2=new MyImg("./images/1.png");
const button = document.querySelector('button');
button.addEventListener('click', function () {
// myImg.scale(2);//
myImg.scale(3); // 3 倍
myImg2.scale(5);
});
</script>
</body>
</html>
<body>
<div class="view"></div>
<button> 大</button>
<script>
function MyImg(src) {
const img = document.createElement(`img`)
img.style.transition = '2s'
img.src = src
this.abc = img
}
MyImg.prototype.appendTo = function (e) {
document.querySelector(e).append(this.abc)
}
MyImg.prototype.scale = function (num) {
this.abc.style.transform = `scale(${num})`
}
const myImg = new MyImg('./images/1.png')
myImg.appendTo(`.view`)
const button = document.querySelector('button')
button.addEventListener('click', function () {
myImg.scale(3)
})
</script>
</body>
再次了解原型
- 万物都是对象
1. 指的是 obj 数据类型
2. 指的是 物体
<script>
// dom 文档对象模型
const div = document.querySelector('div');
const button = document.querySelector('button');
// console.log(div);// 把div的标签形式 显示出来 不方便我去了解 div 对象
console.dir(div);// 把标签 dom元素 以对象的形式显示出来
console.dir(button);
</script>
原型继承-方法
<script>
/*
1 定义一个 父亲 构造函数 有一个方法 say() Person
2 定义两个儿子 构造函数 拥有 爸爸的say方法
1 YellowPerson
2 WhitePerson
*/
function Person() {}
Person.prototype.say = function () {
console.log('这个是父亲定义的say方法');
};
function YellowPerson() {}
// 让儿子去复用父亲的方法
YellowPerson.prototype.say = Person.prototype.say;
// 单独和以前一样添加
YellowPerson.prototype.jump = function () {
console.log('这个黄种人 儿子 自己的方法');
};
function WhitePerson() {}
WhitePerson.prototype.say = Person.prototype.say;
const yp = new YellowPerson();
yp.say();
yp.jump();
// const wp=new WhitePerson();
// wp.say();
// 普通的html标签 div img标签
// div没有src属性 但是id 和 className 属性
// img 有 src属性,但是id 和className
</script>
原型继承-属性
<script>
// 父亲 构造函数 名称 颜色 身高 体重 属性
function Person(name, color, height, weight) {
this.name = name;
this.color = color;
this.height = height;
this.weight = weight;
}
// 儿子 名称 颜色 身高 体重 而且 自己 属性 昵称 、 性别
function YellowPerson(name, color, height, weight, nickname, gender) {
// 父亲中也有
Person.call(this,name, color, height, weight);// 属性的继承 ??
// 儿子
this.nickname = nickname;
this.gender = gender;
}
const yp = new YellowPerson('悟空', '黄色', 150, 250, '弼马温', '公');
console.log(yp);
</script>
对象中的this
<script>
// this 范围很广 主要在 对象中来学习
// this 对象本身 我自己
// this 指向 对象本身 可以被修改 通过 call 方法来修改
// call 帮助我们调用方法 还可以帮助修改 this
// call 在调用方法的时候 还可以传递参数
const obj = {
username: '悟空',
say(a) {
console.log(this,a);
},
};
const newObj={
username:"八戒"
}
obj.say.call(newObj,123);
</script>
###对象添加属性
<script>
// 在对象 this = 对象本身的!! this = 我自己
// 普通的对象
const obj = {
add() {
// 给对象添加属性 两段代码 封装到一个普通的函数中
obj.a = 1;
obj.b = 2;
// ==== 修改this
this.c = 3;
this.d = 4;
},
};
obj.add(); // 让方法帮我们添加属性
console.log(obj);
</script>
通过call来动态添加对象
<script>
// 普通的函数
function Person(name, color, height, weight) {
this.name = name;
this.color = color;
this.height = height;
this.weight = weight;
// =====
// obj.name = name;
// obj.color = color;
// obj.height = height;
// obj.weight = weight;
}
// 定义一个空的对象
const obj={};
Person.call(obj,"悟空","黄色",150,250); // obj 借用了Person方法 来给自己的属性赋值!!
// 1 调用了 Person 方法
// 2 方法内部 给 this赋值 this 等于谁??? obj
// 3 this.name=悟空; => obj.name = 悟空; // 赋值动作
// 3 this.color=黄色; => obj.color = 黄色; // 赋值动作
// 3 this.height=150; => obj.height = 150; // 赋值动作
// 3 this.weight=250; => obj.weight = 250; // 赋值动作
console.log(obj); // 拥有了 Person 函数种 所写的一些属性
</script>
构造函数-实例
<script>
// 我自己 构造函数中的this 指向 实例!!!!!
// function Person(name, color, height, weight) {
// this.name = name;
// this.color = color;
// this.height = height;
// this.weight = weight;
// }
// function YellowPerson(name, color, height, weight) {
// // 借助了父亲里面的代码 快速帮我们 儿子 的属性赋值
// Person.call(this, name, color, height, weight);
// // 1 Person.call 函数 Person(普通的函数即可)被调用
// // 2 Person 函数的作用 给this赋值
// // 3 Person.call(this) call的作用 修改this的指向
// // Person.call(this) this 我自己 = 儿子的构造函数的实例 = yp
// }
// const yp = new YellowPerson('悟空', '黄色', 150, 250);
// console.log(yp);
// 属性的继承 子构造函数 借用了父构造函数的 给 实例赋值代码!!
function Person(name) {
this.username = name;
}
function YellowPerson(name) {
Person.call(this, name); // 属性的继承
}
const yp = new YellowPerson('悟空');
console.log(yp);
</script>
构造函数中属性和方法的继承
<script>
/*
实例 实现 属性和方法的继承
1 属性的继承 在 儿子的构造函数中 调用 父亲的构造函数
父亲的构造函数.call(this,参数。。。)
2 方法的继承 在儿子的构造函数的原型上 等于 父亲的构造函数的原型
儿子的构造函数.prototype.方法名称 = 父亲的构造函数.prototype.方法名称
*/
function Person(name) {
this.name = name;
}
Person.prototype.say = function () {
console.log('父亲的say方法');
};
function YellowPerson(name, color) {
Person.call(this, name); // 属性的继承
this.color = color;
}
YellowPerson.prototype.say = Person.prototype.say;
YellowPerson.prototype.fly = function () {
console.log('儿子自己的方法 fly');
};
</script>
封装+继承案例需求
<script>
/*
案例 : 目的 利用 面向对象的语法和思想 来结合 dom操作 解决实际的问题
1 定义父构造函数
HTMLElement
1 属性 dom
2 方法 appendTo
2 定义 一个儿子 HTMLDivElement
1 会继承 父亲 属性和方法
2 儿子还有自己独立的功能
const myDiv = new HTMLDivElement("div中的文本")
myDiv.appenTo("p") ; p标签中会多出有一个 文本为 “div中的文本” 的div
儿子还会有自己的一个方法
点击按钮 myDiv.scale(2); 缓慢放大两倍
3 定义 另外一个儿子 HTMLImgElement
1 会继承 父亲 属性和方法
2 自己独立的功能
const myImg = new HTMLImgElement(图片的地址)
myImg.appendTo("a") a标签中会多了一个 图片标签
儿子还会有自己的一个方法
点击某个按钮 myImg.borderRadius("50%") 缓慢变成 边框圆角 50% 效果
4 代码提示
1 先根据需求 把 代码的解构整理好
2 再去思考实现的逻辑
*/
function HTMLElement() {
// this.dom=....
}
HTMLElement.prototype.appentTo=function(){
}
</script>
封装和继承的案例实现
<button>div放大两倍</button>
<div class="box"></div>
<script>
/*
HTMLElement
1 属性 dom
2 方法 appendTo
*/
function HTMLElement() {
this.dom = document.createElement('div');
}
HTMLElement.prototype.appendTo = function (selector) {
document.querySelector(selector).append(this.dom);
};
// 儿子
function HTMLDivElement(text) {
HTMLElement.call(this); // this上多一个属性 dom dom = 动态创建的 div元素
// this.dom = 真实的div 的dom元素
this.dom.innerText = text;
this.dom.style.textAlign = 'center';
}
// 继承父亲的方法
HTMLDivElement.prototype.appendTo = HTMLElement.prototype.appendTo;
// 自己的方法
HTMLDivElement.prototype.scale = function (num) {
this.dom.style.transition = '2s';
this.dom.style.transform = `scale(${num})`;
};
const divEle = new HTMLDivElement('div中的文字');
// console.log(divEle);
divEle.appendTo('.box');
const button = document.querySelector('button');
button.addEventListener('click', function () {
divEle.scale(2);
});
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>13-实现-封装和继承案例.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<button>div放大两倍</button>
<input type="button" value="设置图片缓慢边框圆角效果" />
<div class="box"></div>
<script>
function HTMLElement(tagName) {
this.dom = document.createElement(tagName);
}
HTMLElement.prototype.appendTo = function (select) {
document.querySelector(select).append(this.dom);
};
function HTMLDivElement(text) {
HTMLElement.call(this, 'div');
this.dom.innerText = text;
this.dom.style.textAlign = 'center';
}
HTMLDivElement.prototype.appendTo = HTMLElement.prototype.appendTo;
HTMLDivElement.prototype.scale = function (num) {
this.dom.style.transition = '2s';
this.dom.style.transform = `scale(${num})`;
};
function HTMLImgElement(src) {
HTMLElement.call(this, 'img');
this.dom.src = src;
}
HTMLImgElement.prototype.appendTo = HTMLElement.prototype.appendTo;
HTMLImgElement.prototype.borderRadius = function (num) {
this.dom.style.transition = '2s';
this.dom.style.borderRadius = num;
};
const divEle = new HTMLDivElement('div中的文字');
const imgEle = new HTMLImgElement('./images/1.png');
divEle.appendTo('.box');
imgEle.appendTo('.box');
const input = document.querySelector('input');
const button = document.querySelector('button');
input.addEventListener('click', function () {
imgEle.borderRadius('50%');
});
button.addEventListener('click', function () {
divEle.scale(2)
});
</script>
</body>
</html>
类的基本使用
<script>
/*
1 构造函数 来创建对象
2 对象 两种信息
1 属性
2 方法
*/
// es6 新 简洁 class 面向对象
class Person {
name = '悟空';
color = '黄色';
say() {
console.log(this.name, this.color);
}
fly(){
console.log(this.name,"起飞");
}
}
// es5 原型链方式实现 面向对象
// function Person() {
// this.name="悟空";
// this.color="黄色";
// }
// Person.prototype.say=function(){
// console.log(this.name,this.color);
// }
const p1 = new Person();
p1.say();
p1.fly();
</script>
<script>
/*
1 使用 class来定义属性的时候
1 如果 这个属性 你写死
class Person {
name="悟空";
color="黄色";
}
2 如果 属性 可以由外部传入 必须使用构造器
constructor(name,color){
this.name=name;
this.color=color;
}
*/
class Person {
// 构造器
constructor(name, color) {
// 当 Person被new的时候 这个构造器 就会被调用
console.log('person被new啦');
// console.log(name,color);
// this 还是指向 实例
this.name = name;
this.color = color;
}
say() {
console.log(this.name, this.color);
}
}
const p1 = new Person('悟空', '黄色');
console.log(p1);
</script>
类的方式来实现继承
<script>
/*
父构造函数 Person
1 属性 name = "父亲"
2 方法 say 说话
儿子 去继承 父亲
1 属性
2 方法
*/
// function Person() {
// this.name="父亲";
// }
// Person.prototype.say=function(){
// console.log(this.name,"父亲的say方法");
// }
// function YellowPerson() {
// Person.call(this);
// }
// YellowPerson.prototype.say=Person.prototype.say;
// es6 类去实现继承
class Person {
name = '父亲';
say() {
console.log(this.name, '父亲的say方法');
}
}
// 直接就实现了 继承父亲的属性和方法 !!!!
class YellowPerson extends Person {}
// 儿子实例 拥有 父亲 name属性和父亲的 say方法
const yp = new YellowPerson();
console.log(yp);
</script>
<script>
/*
对于子类来说
1 如果你写了 extends 而且 还写 constructor
那么在我们的 constructor 必须要调用super 固定语法!!
2 为什么 之前只写 extends 不用写super-没有写 constructor
*/
class Person {
constructor(name, color) {
this.name = name;
this.color = color;
}
}
class YellowPerson extends Person {
// 默认的代码
constructor(name, color, height, weight) {
super(name, color);// 调用父亲的构造器 给儿子 添加属性
this.height = height;
this.weight = weight;
}
}
const yp = new YellowPerson('悟空', '黄色', 100, 200);
console.log(yp);
</script>