前端基础1-2 :面向对象 + Promise

面向对象

对象是什么?为什么要面向对象?

通过代码抽象,进而藐视某个种类物体的方式

特点:逻辑上迁移更加灵活、代码复用性更高、高度的模块化
对象的理解
  • 对象是对于单个物体的简单抽象
  • 对象是容器,封装了属性 & 方法
    • 属性:对象状态
    • 方法:对象的能力 & 行为
//简单对象
const O = {
	name:'zhangsan',
	changeName: name => `新的${name}`
}
//函数对象
function O(){
	this.name = '张三'
	this.changeName = name => `新的${name}`
}

构造函数 - 生成对象 => 实例

  • 需要一个模板
  • 类即对象模板
  • js本质并不是基于类,而是基于构造函数(创建对象的特殊函数)+原型链
function Course() {
    this.name = 'zhangsan';
    this.changeName = name => `新的${name}`
}
const course = new Course(args);

Course本质就是构造函数

  • 函数体内使用的this,指向要生成的实例
  • 生成对象用new来实例化
  • 可以初始化传参
如果构造函数不初始化,可以使用具有相同功能吗? --无法具有
如果在项目中需要使用,且不希望外界感知的情况下,如何拿到实例后的对象? => 单例模式 (编写底层api代码时,尽量做到不让外部去感知区分内部类型)
function Course(){
	const _isClass = this instanceof Course
	if(!_isClass){
		return new Course()
	}
	this.name = 'zhangsan'
	this.changeName = name => `新的${name}`
}
//使用
const course = Course()
思考:new是什么?/ new的原理? / new时候做了什么?
function Course(){}
const course = new Course()
  • 结构上:创建了一个空对象,作为返回的对象实例
  • 属性上:将生成空对象的原型对象指向了构造函数的prototype属性(course._ proto _=== Course.prototype)
  • 关系上:将当前对象实例赋给了内部的this
  • 生命周期上:执行了构造函数的初始化代码
function usernew(obj,...args){
	const newObj = Object.create(obj.prototype)
	const result = obj.apply(newObj,args)
	return typeof result === 'object' ? result : newObj
}
追问:实例属性影响 —— 独立的
function Course(teacher, leader) {
    this.teacher = teacher;
    this.leader = leader;
}
const course1 = new Course('张三', '王五'); // course1.leader => 王五
const course2 = new Course('李四', '赵六'); // course2.leader => 赵六
course2.teacher = 'xxxx'; // course1.teacher => 李四
constructor是什么?
 function Course(teacher, leader) {
    this.teacher = teacher;
     this.leader = leader;
 }
 const course = new Course('张三', '李四');
  • 每个对象在创建时,会自动拥有一个构造函数属性constructor

  • constructor源自原型对象,指向了构造函数的引用

  • 实例获得了模版的属性 => (大胆点)继承了类的属性

在这里插入图片描述

继承

js如何实现继承

在原型对象的所有属性方法,都可以被实例所共享
    function Game() {
        this.name = 'lol';
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    // LOL
    function LOL() {};
    LOL.prototype = new Game();
    LOL.prototype.constructor = LOL;
    const game = new LOL();
    // 本质:重写了原型对象方式,将父对象的属性方法,作为自对象原型对象的属性方法,同时重写构造函数
追问:原型链直接继承有什么缺点
    function Game() {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    // LOL
    function LOL() {};
    LOL.prototype = new Game();
    LOL.prototype.constructor = LOL;
    const game1 = new LOL();
    const game2 = new LOL();
    game1.skin.push('ss');
    // 本质:重写了原型对象方式,将父对象的属性方法,作为自对象原型对象的属性方法,同时重写构造函数
    1. 父类属性一旦赋值给到子类的原型属性,此时属性属于子类的共享属性了
    1. 实例化子类时,无法向父类进行传参

解决方法:构造函数继承

经典继承:在子类的构造函数内部调用父类的构造函数
    function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function LOL(arg) {
        Game.call(this, arg);
    }

    const game3 = new LOL('arg');
    // 解决了共享属性问题 + 子向父传参的问题

追问:原型链上的共享方法无法被读取继承,如何解决?

组合继承
    function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function LOL(arg) {
        Game.call(this, arg);
    }
    LOL.prototype = new Game();
    LOL.prototype.constructor = LOL;
    const game4 = new LOL('arg');

追问:组合继承方式就没有缺点吗? 问题在于:无论何种场景,都会调用两次父类的构造函数

解决方案:寄生组合继承
    function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function LOL(arg) {
        Game.call(this, arg);
    }
    LOL.prototype = Object.create(Game.prototype);
    LOL.prototype.constructor = LOL;
    const game5 = new LOL('arg');

拔高:如何实现多重继承?

    function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function Store() {
        this.shop = 'steam';
    }
    Game.prototype.getPlatform = function() {
        return this.shop;
    }

    function LOL(arg) {
        Game.call(this, arg);
        Store.call(this, arg);
    }

    LOL.prototype = Object.create(Game.prototype);
    Object.assign(
        Store.prototype,
        LOL.prototype
    );
    LOL.prototype.constructor = LOL;

浏览器原理

在这里插入图片描述

Promise - 可以处理回调地狱

    1. promise状态 - pending | fulfilled | rejected
      executor: new Promise的时候立即执行,接收两个参数 resolve | reject
    1. promise默认状态?状态是如何流转的? - 默认:pending 状态流转:pending => fufilled | pending => rejected
      内部维护成功value:undefined | thenable | promise
      内部维护失败变量reason
    1. promise返回值? - then方法:接收onFulfilled 和 onRejected
      如果then时,promise已经成功,执行onFulfilled,参数value
      如果then时,promise已经失败,执行onRejected,参数reson
      如果then中有异常,执行onRejected
Promise 方法
  1. Promise.all 全部执行完成
  2. Promise.race 有一个执行完成
手写promise
    const PENDING = 'PENDING';
    const FULFILLED = 'FULFILLED';
    const REJECTED = 'REJECTED';

    class Promise {
        constructor(executor) {
            // 1. 默认状态 - PENDING
            this.status = PENDING;
            // 2. 内部维护的变量值
            this.value = undefined;
            this.reason = undefined;

            // 成功的回调
            let resolve = value => {
                // 单向流转
                if (this.status === PENDING) {
                    this.status = FULFILLED;
                    this.value = value;
                }
            }

            // 失败的回调
            let reject = reason => {
                // 单向流转
                if (this.status === PENDING) {
                    this.status = REJECTED;
                    this.reason = reason;
                }
            }

            try {
                executor(resolve, reject);
            } catch (error) {
                reject(error);
            }
        }

        then(onFulfilled, onRejected) {
            if (this.status === FULFILLED) {
                onFulfilled(this.value);
            }
            if (this.status === REJECTED) {
                onRejected(this.reason);
            }
        }
    }

    // 追问:异步怎么办?
    const PENDING = 'PENDING';
    const FULFILLED = 'FULFILLED';
    const REJECTED = 'REJECTED';

    class Promise {
        constructor(executor) {
            // 1. 默认状态 - PENDING
            this.status = PENDING;
            // 2. 内部维护的变量值
            this.value = undefined;
            this.reason = undefined;

            // 存放回调
            this.onResolvedCallbacks = [];
            this.onRejectedCallbacks = [];

            // 成功的回调
            let resolve = value => {
                // 单向流转
                if (this.status === PENDING) {
                    this.status = FULFILLED;
                    this.value = value;
                    this.onResolvedCallbacks.forEach(fn => fn());
                }
            }

            // 失败的回调
            let reject = reason => {
                // 单向流转
                if (this.status === PENDING) {
                    this.status = REJECTED;
                    this.reason = reason;
                    this.onRejectedCallbacks.forEach(fn => fn());
                }
            }

            try {
                executor(resolve, reject);
            } catch (error) {
                reject(error);
            }
        }

        then(onFulfilled, onRejected) {
            if (this.status === FULFILLED) {
                onFulfilled(this.value);
            }
            if (this.status === REJECTED) {
                onRejected(this.reason);
            }
            if (this.status === PENDING) {
                // 存放队列
                this.onResolvedCallbacks.push(() => {
                    onFulfilled(this.value);
                });
                this.onRejectedCallbacks.push(() => {
                    onRejected(this.reason);
                });
            }
        }
    }
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值