前端JS-Day24

JS高级:

面向过程编程POP:分析解决问题的步骤,按照步骤解决问题。

 

 

 面向对象编程POP:将事务分解为一个个对象,按照对象的功能来解决问题。

 

 

面向对象编程具有灵活、易于维护和开发、代码可复用的特点。

面向对象的三大特性:封装性、继承性、多态性

构造函数体现了面向对象的封装特性。

面向对象比面向过程性能低!

 

 对象:特指的某一个,通过类实例化产生的对象。

 

 类:抽取了对象的公共部分,泛指的某一大类

 

面向对象思维特点:

1.抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)

2.对类进行实例化、获取类的对象。

 

创建类:

1.通过class关键字创建类,通过new关键字生成实例。

2.类里有constructor函数,可以接受传入的参数,同时返回实例对象。

3.constructor函数是只要new生成实例时就会调用,不编写该函数,也会自动生成并去调用。

4.语法规范:创建类名后不需要加括号,生成实例类后加小括号,构造函数不需要加fuction!

5.多个函数间不需要加逗号!

 

类的继承:extends关键字、super关键词

extends:用于子类继承父类的属性和方法。

super:用于在子类中调用父类的函数,可以调用父类的构造函数或普通函数。

复制代码
<script>
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);
            }
        }

        class Son extends Father {
            constructor(x, y) {
                super(x, y);
                // 调用父类的构造函数!
            }
        }
        let son = new Son(2, 4); //输出6
        son.sum();
    </script>
复制代码

继承中的属性和方法的查找原则:就近原则

继承中,如果实例化子类输出一个方法,先看子类是否拥有该方法,如果有就先执行子类的,否则去执行父类中的方法。

 

子类构造函数中,super必须在this之前使用(必须先调用父类构造方法,再去使用子类构造方法)!

复制代码
<script>
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
        }
        class Son extends Father{
            constructor(x, y) {
                super(x, y);
                this.x = x;
                this.y = y; 
                // super必须在子类this之前调用
            }
        }
</script>
复制代码

注意事项:

ES6中类没有变量提升,故必须先定义类,才能通过类实例化对象。
类里面的共有属性和方法一定要加this使用!
this指向问题:constructor中的this指向实例对象,方法中的this指向方法的调用者。
 
旧版添加元素:通过createElement方法创建,innerHTML赋值,appendChild添加元素。
新版添加元素:通过insertAdjacentHTML方法直接将字符串格式元素添加到父元素中!
appendChild不支持追加字符串的子元素,insertAdjacentHTML支持。
insertAdjacentHTML(position,text):position为插入位置,text为插入元素即html语句。
position分为:beforebegin:插入元素自身之前
beforeend:元素内部的最后一个节点之后,相当于appendChild
afterbegin:元素内部的第一个节点之前
afterend:插入元素自身之后
 
鼠标双击事件:ondblclick
 
构造函数和原型:
创建对象三种方法:1.对象字面量、2.new Object()、3.自定义构造函数

new的执行机制: 

 

 

实例成员:通过构造函数创建的对象为实例对象,实例对象中的属性和方法就是实例成员,实例成员只能通过实例化对象来进行访问。
静态成员:构造函数的属性和方法被称为静态成员,静态成员只能通过构造函数来访问+。
 
构造函数存在浪费内存空间的问题,所以引入构造函数原型prototype的概念。
构造函数原型prototype(原型对象):存放构造函数的属性,默认指向空对象即原型对象。构造函数和原型对象的this都指向实例化对象!
规定:一般来说,将公共属性放入构造函数中,将公共方法放入原型对象上。
 
对象原型__proto__:每个实例化对象都具有的属性,指向构造函数的prototype原型对象,实现继承的重要属性。
__proto__ 和[[prototype]]意义相同! __proto__是只读属性!

即每个对象实例都有一个对象原型属性__proto__,执行某些方法时,若对象自身没有该方法,则通过对象原型属性去寻找构造函数原型对象prototype中的方法。

复制代码
<script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Star.prototype.sing = function () {
            console.log('原型对象');
        }
        let a = new Star('a', 1);
        console.log(a.__proto__ === Star.prototype); //true
        // a.proto即实例化对象的原型对象  Star.prototype即对象原型
</script>
复制代码

 

constructor函数:即构造函数本身,该属性被__proto__(对象原型)和prototype(原型对象)共有。

 

constructor用于指回构造函数:当原型以对象形式赋值时导致覆盖,就要利用constructor导回!

关键点:↓↓↓↓↓↓↓↓↓↓↓↓

如果对对象原型以对象的形式进行赋值,会造成对象的覆盖,导致实例化对象的constructor无法将指回到构造函数本身,这时我们要采用constructor属性对其进行重新定向,令其重新指回到对象的构造函数本身。

复制代码
function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }

        Star.prototype = {
            constructor: Star,
            // 指回Star对象
            sing: function () {
                console.log('原型对象');
            },
            dance: function () {
                console.log('constructor');
            }
        }
        // 相当于对对象原型赋值,造成对象覆盖,constructor无法指回
复制代码

 构造函数,实例,原型对象的三角关系:每个构造函数都有一个prototype原型对象,每一个对象都有一个__proto__属性,指向他的prototype原型对象。

 

原型链:现有的构造函数、原型对象、对象实例之间的链式关系。

每个对象都有一个__proto__属性,它指向prototype原型对象。而prototype原型对象又具有一个自己的prototype原型对象,同样通过原型__proto__属性指向,这样层层往上直到Object原型对象的prototype为null。

 

 Javascript的原型链成员查找机制:就近原则,依靠__proto__属性向上查找它的原型(类似继承)

 

 

instanceof:用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,简单来说就是检测是否属于某个构造函数。

 

原型对象的this指向:构造函数和原型对象中的this都指向实例对象(即调用者)

扩展内置对象:只能采取对象.prototype.方法名 = fuction(){}的方法扩展。

复制代码
<script>
        console.log(Array.prototype);
        Array.prototype.sum = function() {
            let sum = 0;
            for(let i =0; i < this.length; i++) {
                sum += this[i];
            }
            return sum;
        }

        let a = [1,2,3];
        console.log(a.sum());
        console.log(Array.prototype);
        console.log(a.__proto__);
</script>
复制代码

继承:在ES6之前不存在extends关键字:

① 需要通过构造函数+原型链的方式实现继承,即组合继承。使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。

② 直接通过构造函数+原型对象的方式实现原型继承。

1.组合继承:

call函数:1.直接调用函数 2.修改this指向

复制代码
<script>
        function fn () {
            console.log('213');
            console.log(this);
        }

        var o = {
            name: 'lwh'
        };

        // 1.call()调用函数
        fn.call();
        // 输出213 和 window对象

        // 2.修改this指向
        fn.call(o); 
        // 输出213 和 o对象
    </script>
复制代码

利用call方法可以实现继承关系,call修改this指向,并将相同参数传入其中,自定义参数则再用this创建。类似于es6中的super方法和extends一同实现。

复制代码
 <script>
        function Father (uname, age) {
            this.uname = uname;
            this.age = age;
        }

        function Son(uname, age, score) {
            Father.call(this, uname, age);
            this.score = score;
        }
        // ES5
class Fathers { constructor(uname, age) { this.uname = uname; this.age = age; } } class Sons extends Fathers{ constructor(uname, age, score) { super(uname, age); this.age = age; } } // ES6 </script>
复制代码

借用父构造函数继承方法:ES6后使用extends即可,在ES5时,需要采用给子对象的原型对象赋值为父元素。

组合继承的最终形式:① 使用父类的构造函数生成自己的属性利用call改变this ② 利用子构造函数的原型prototype指向new Father()继承到父类的属性和方法。③ 最后使Son原型的constructor指回Son。

即子元素的prototype即子元素的原型对象成为了一个新的父元素的实例,但此时子元素的原型对象已发生改变,所以要修改原型对象的constructor值,使其重新指回子元素的构造函数。由于__proto__对象原型的存在,故能继承到父类的方法。

复制代码
function Father (uname, age) {
            this.uname = uname;
            this.age = age;
        }

        Father.prototype.money = function (){
            console.log('$$$');
        }

        Son.prototype = new Father();
        Son.prototype.constructor = Son;

        function Son(uname, age, score) {
            Father.call(this, uname, age);
            this.score = score;
        }
复制代码

原型继承:

原型继承的问题:直接给Man和Women的原型对象设置为Person会导致地址相同,对原型修改则对Person也进行了修改成为了公共方法,故只给women设置的方法会被man访问!

复制代码
const Person = {
            eyes: 2,
            head: 1
        }
        Women.prototype = Person;
        Women.prototype.constructor = Women;
        function Women() {
        }
        Women.prototype.baby = function () {
            console.log(123);
        }
        Man.prototype = Person;
        Man.prototype.constructor = Man;
        function Man() {
        }
        const p1 = new Women();
        const p2 = new Man();
        console.log(p1.baby());
        console.log(p2.baby()); //此时均可输出baby的方法
复制代码

原型继承的改进:对父类进行构造函数的封装,然后再对子对象的原型进行new实例化:(原型继承)

复制代码
function Person() {
            this.eyes = 2;
            this.mouth = 1;
        }

        Women.prototype = new Person();
        Women.prototype.constructor = Women;
        function Women() {
        }
        Women.prototype.baby = function () {
            console.log(123);
        }

        Man.prototype = new Person();
        Man.prototype.constructor = Man;

        function Man() {
        }
        const p1 = new Women();
        const p2 = new Man();

        console.log(p1.baby());
        console.log(p2.baby());
复制代码

 

 

posted @   HM-7  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
点击右上角即可分享
微信分享提示