目录
🏆 //面向对象与面向过程,是解决问题的两种思路
//面向过程:先分析问题中的步骤,马上将分出来的步骤封装成函数,再按顺序依次调用即可解决问题
//面向对象:先分析问题中的步骤,再将步骤划分不同的不同主体上,最的将顺序调用主体上方法
- //早晨起床上学
- //面向过程
- /*
- //起床
- function getUp(){}
- //洗澡
- function wash(){}
- //吃饭
- function eat(){}
- //去上学
- function toscholl(){}
- getUp()
- wash()
- eat()
- */
-
- //面向对象
- let stu = {
- getUp: function () { },
- //洗涑
- wash: function () { },
- //吃饭
- eat: function () { },
- //去上学
- toscholl: function () { }
- }
- stu.getUp()
- stu.wash()
- stu.eat()
面向过程
优点:执行效率更高
缺点:当一个项目很大的时候,维护很困难,功能扩展几乎是没有
//面向对象
// 优点:对于应该后期维护,与功能扩展相对于面向过程更容易
// 缺点:执行效率没有面向过程高
//面向对象的三大特性:
//1.封装:严格的书写类,将方法与方法中的属性,封装到对象上(数据与操作数据的方法必须依附于一个主体)
//2.多态:多种形态,根据参数的个数不同,参数的类型不同,可以调用不同的方法
//3.继承:一个类继承另一个类
//提示:
//Js并不是纯正的面向对象语言,面向对象的三大特性,封装与继承体现的会多一点
🏆 封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。
// 同样的将变量和函数组合到了一起并能通过 this 实现数据的共享,所不同的是借助构造函数创建出来的实例对象之间是彼此不影响的
// 总结:
// 1. 构造函数体现了面向对象的封装特性
// 2. 构造函数实例创建的对象彼此独立、互不影响
- function Person(uname, age) {
- this.uname = uname
- this.age = age
- this.sing = function () {
- console.log('唱歌')
- }
- }
- // new
- const ldh = new Person('刘德华', 58)
- // console.log(ldh)
- const zxy = new Person('张学友', 59)
- // console.log(zxy)
- // ldh.sing()
- // zxy.sing()
- //构造函数里面的方法会存在浪费内存的问题
// 封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。
💎构造函数方法很好用,但是 存在浪费内存的问题
// 🏆 利用原型对象实现方法共享
// 构造函数通过原型分配的函数是所有对象所 共享的。
// JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象
// 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
// 💎我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。
// 💎构造函数和原型对象中的this 都指向 实例化的对象
💎js规定:如果要给构造函数添加方法不要再构造函数内部添加最好的方法就 是给构造函数的原型对象添加方法
- function Star(uname, age) {
- this.uname = uname
- this.age = age
- }
- console.log(Star.prototype)//返回一个对象
-
- //🏆每个构造函数 都有一个属性「prototype」属性的值是一个对象原型对象
- //💎js规定:如果要给构造函数添加方法不要再构造函数内部添加最好的方法就 是给构造函数的原型对象添加方法
- Star.prototype.sing = function () {
- console.log('我会唱歌')
- }
- const ldh = new Star('刘德华', 18)
- const zxy = new Star('张学友', 19)
- console.log(ldh.sing === zxy.sing)//true
- ldh.sing()
- zxy.sing()
//🏆 每个原型对象里面都有个constructor 属性(constructor 构造函数)
// 作用:该属性指向该原型对象的构造函数, 简单理解,就是指向我的爸爸,我是有爸爸的孩子
//🏆 constructor属性的作用
// 使用场景:
// 如果有多个对象的方法,我们可以给原型对象采取对象形式赋值.
// 但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了
// 此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
- // function Star(name, age) {
- // this.name = name
- // this.age = age
-
- // }
- // Star.prototype = {
- // sing: function () { console.log('唱歌') },
- // dance: function () { console.log('跳舞') }
- // }
- // const ldh=new Star('刘德华',78)
- // console.log(ldh);
- // //构造函数的原型对象被重新赋值,constructor此时不是Star,而是新的Object
- // console.log(ldh.__proto__.constructor===Star);//false
- function Star(name) {
- this.name = name
- }
- Star.prototype = {
- // 我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
- constructor: Star,
- sing: function () { console.log('唱歌') },
- dance: function () { console.log('跳舞') }
- }
- const ldh = new Star('刘德华', 78)
- console.log(ldh);
- console.log(ldh.__proto__.constructor === Star);//true
- console.log(Star.prototype.constructor)//指向 Star

//🏆对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,
// 之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,
// __proto__
//就是因为对象有 __proto__ 原型的存在。
// 💎注意:
// __proto__ 是JS非标准属性
// [[prototype]]和__proto__意义相同
// 用来表明当前实例对象指向哪个原型对象prototype
// __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数
//🏆子构造函数继承父构造的属性
- //🏆子构造函数继承父构造的属性
- function Product(name, price) {
- this.name = name;
- this.price = price;
- console.log(this);//this是f1,因为call改变了this指向
- }
-
- function Food(name, price) {
- //借用父构造函数将Product函数当成普通函数在调用
- //
- Product.call(this, name, price);
- this.category = 'food';
- }
-
- // 实例化food构造函数
- const f1 = new Food('rice', 6)
- // expected output: "cheese"
- console.log(f1)
//🏆 cal1()可以改变函数里面的this指向 函数名.cal1(对象)
// 函数名.call(对象,函数里面的参数,函数里面的参数)
//通过 var声明的全局变量相当于给 window对象添加属性
//函数相当于给window对象添加的方法
- function f(x, y, z) {
- console.log(this, x, y,z);
- }
-
- const obj = {
- unname: '张三'
- }
- f.call(obj, 10, 20, 30)//this变成了obj

//🏆子构造函数继承父构造的方法
-
- function Product(name, price) {
- this.name = name;
- this.price = price;
- // console.log(this);//this是f1,因为call改变了this指向
- }
- // 给Product 构造函数的原型对象添加方法
- Product.prototype.sayHello = function () {
- console.log('hello!!!');
- }
-
- function Food(name, price) {
- //借用父构造函数将Product函数当成普通函数在调用
- //
- Product.call(this, name, price);
- this.category = 'food';
- }
-
- // Food.prototype = Product.prototype
- // 将实例化的父构造函数 的实例化对象 赋值给 子构造函数的原型对象
- //可以避免改变子构造函数的原型对象,父元素的原型对象也会改变
- Food.prototype = new Product()
-
- Food.prototype.sss = function () {
- console.log('我是food里的方法');
- }
-
- // 实例化food构造函数
- const f1 = new Food('rice', 6)
- // expected output: "cheese"
- console.log(f1)
- f1.sss()
注意:
1.如果使用Food.prototype = Product.prototype ,会出现改变子构造函数的原型对象,父元素的原型对象也会改变

2.如果使用 Food.prototype=new Product()
不会修改父元素的原型对象的方法,原因是,new出来的Product()实例化对象 作为子元素的原型对象,新增的方法在旧方法的原型外部

//🏆组合式继承:借用构造函数继承(继承属性)+原型链继承(继承方法)
继承属性:子构造函数中使用函数call方法,调用父构造函数,传入(this,参数)
继承方法:
- function Product(name, price) {
- // this.name = name;
- // this.price = price;
- // console.log(this);//this是f1,因为call改变了this指向
- }
- // 父元素的原型对象的方法
- function Food(name, price) {
- //借用父构造函数将Product函数当成普通函数在调用
- // Product.call(this, name, price);
- // this.category = 'food';
- }
-
-
- // 父元素原型对象增加方法
- Product.prototype.sayHello = function () {
- console.log('hello');
- }
-
- Food.prototype=new Product()//之所以不会修改父元素的原型对象的方法,原因是,new出来的Product()实例化对象既包含属性和方法,只是属性没有传参,
-
- // Food.prototype = Product.prototype
- // Food.prototype = new Product().__proto__
-
- // 对子元素原型对象增加方法
- Food.prototype.dance = function () {
- console.log('跳舞');
- }
-
- const s1 = new Food('周杰伦', 90)
- console.log(s1);
- s1.sayHello()
- s1.dance()
-
-
- const f1 = new Product('周杰伦', 90)
- console.log(f1);
- f1.sayHello()
- f1.dance()
// 🏆 基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对
// 象的链状结构关系称为原型链
// 🏆原型链-查找规则
// ① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
// ② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象) ③ 如果还没有就查找原型对象的原型(Object的原型对象) ④ 依此类推一直找到 Object 为止(null) ⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
// 💎可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
// 判断实例对象和构造函数之间的关系
// 通过的方式是,判断构造函数.prototype是否在实例对象的原型链上
- function Person() { }
- let p1 = new Person();
- function Mobile() { }
- let m1 = new Mobile();
- console.log(p1 instanceof Person);//true
- console.log(m1 instanceof Mobile);//true
-
- console.log(p1 instanceof Mobile);//false