IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Javascript高级的学习 -> 正文阅读

[JavaScript知识库]Javascript高级的学习

继承

当一个不具有某个功能或特征的事物,通过某种方式,能够使用另一个具有某个功能或特征的事物的功能或特征的方式叫继承

实例和类的关系是基本的继承

function fn(n){
    this.name = n
}
fn.prototype.show = function(){
    console.log(this.name)
}
var f = new fn("admin")
f.name
f.show();
// new的原理
    // 1. 创建一个新对象
    // 2. 改变函数的this指向这个新对象
    // 3. 将这个新对象的原型属性__proto__指向了函数的原型对象prototype
    // 4. 检测原函数是否主动返回对象,如果没有,返回这个新对象

类与类之间的继承

改变this指向的继承

  • 构造函数继承
  • 只能继承构造函数的内容,不能继承原型上的内容
  • 多继承
// 改变this指向继承
function test01() {
    this.test01 = "test01"
}

function test02() {
    this.test02 = "test02"
}

function test03() {
    this.test03 = "test03"
}

function test() {
    this.test = "test";
    test01.call(this);
    test02.apply(this);
    // 因为bind返回的返回值是改变this执行之后的新函数,所以需要执行这个新函数
    test03.bind(this)();
}

const otest = new test();
console.log(otest);

原型继承 - 原型对象继承 - 拷贝的是prototype

  • 只能继承原型对象上的内容,不能继承构造函数的内容
  • 注意参数的传递
  • 原型对象是一个对象!注意拷贝方式,深拷贝
  • 多继承
function test1() {}
test1.prototype.show = function () {
    console.log("This is test1's method");
}

function test2() {}
test2.prototype.say = function (msg) {
    this.msg = msg;
    console.log(this.msg);
}

const t1 = new test1();
const t2 = new test2();
t2.say("test")
console.log(t1)
console.log(t2)

function test() {}
// 用对象的深拷贝复制其他的对象
for (let i in test1.prototype) {
    test.prototype[i] = test1.prototype[i];
}
for (let i in test2.prototype) {
    test.prototype[i] = test2.prototype[i];
}
const test3 = new test();
test3.say("test3")

console.log(test3)
console.log(test3.show())

原型继承 - 原型链继承

  • 既能继承构造函数的内容,又能继承原型对象上的内容
  • 不方便处理参数
  • 不方便实现多继承
  • 会多消耗一些性能,多了一层原型链
function Test(msg) {
    this.info = msg;
}
Test.prototype.say = function () {
    console.log(this.info);
}

const test = new Test("test");
test.say();
console.log(test)
console.log(test.info)

function Test2(msg) {
    
}

Test2.prototype=new Test("test2");
const test2 = new Test2();

// test2.say = function(){
//     console.log("info")
// }

console.log(test2);
console.log(test2.info);
// console.log(test2.say())

混合继承 - 改变this指向+原型对象继承

  • 既能继承构造函数的内容,又能继承原型上的内容
  • 原型对象是一个对象!注意拷贝方式,深拷贝
  • 多继承
function Test(msg) {
    this.msg = msg;
    this.show = function () {
        console.log(this.msg)
    }
}
Test.prototype.say = function () {
    console.log("I am test");
}

const test = new Test("test");
test.show()
test.say();
console.log(test);

function Test01(msg) {
    // 改变this指向只能继承构造函数
    Test.call(this, msg);
}
// 继承Test的原型对象
Test01.prototype={
    constructor:Test01,
    // 展开Test对象的prototype中的属性然后赋值给Test01的prototype中的属性(对象的拷贝,有深浅拷贝)
    ...Test.prototype,
    say1:function(){
        console.log("I am test1")
    }
};

const test01 = new Test01("test1");
console.log(test01);
test01.say()
test01.say1()

ES6提供的class继承

  • 语法层面上的继承
  • 原理:构造函数继承+原型链继承
class Test {
    constructor(msg) {
        this.msg = msg;
        this.say();
    }
    say() {
        console.log("I am " + this.msg)
    }
}

const test = new Test("test");
console.log(test);
test.say();

class Test01 extends Test{
    constructor(msg){
        super(msg);
    }
}
const test1 = new Test01("test1");
console.log(test1);
test1.say();

继承的应用场景
只要有重复功能出现,就可以将重复功能抽象成公共类,其他原有类都先继承公共类,再做具体的实现

例子-拖拽的继承

html

<div class="box1"></div>
<div class="box2"></div>

css

div {
    width: 100px;
    height: 100px;
    position: absolute;
}

.box1 {
    background-color: cornflowerblue;
}

.box2 {
    top: 200px;
    background-color: darkslateblue;
}

js

// 拖拽的功能
// 公共类
class Drag {
    // ele是要操作的元素
    constructor(ele) {
        this.ele = ele;
        this.clientWidth = document.documentElement.clientWidth;
        this.clientHeight = document.documentElement.clientHeight;
        this.addEvent();
    }
    addEvent() {
        const that = this;
        this.ele.addEventListener("mousedown", function (eve) {
            // 添加事件对象,方便后面获取坐标
            that.downE = eve || window.event;
            that.down();
        });
    }

    down() {
        const that = this;
        document.onmousemove = function (eve) {
            that.moveE = eve || window.event;
            that.move();
        }
        document.onmouseup = function () {
            document.onmousemove = document.onmouseup = null;
        }
    }

}

class Drag1 extends Drag {
    constructor(ele) {
        super(ele);
    }
    move() {
        this.ele.style.left = this.moveE.pageX - this.downE.offsetX + "px";
        this.ele.style.top = this.moveE.pageY - this.downE.offsetY + "px";
    }
}


const box1 = document.querySelector(".box1");
const test1 = new Drag1(box1);
console.log(test1);


class Drag2 extends Drag {
    constructor(ele) {
        super(ele);
    }
    move() {
        let left = this.moveE.pageX - this.downE.offsetX;
        let top = this.moveE.pageY - this.downE.offsetY;
        if (left <= 0) {
            left = 0;
        } else if (left >= this.clientWidth - this.ele.offsetWidth) {
            left = this.clientWidth - this.ele.offsetWidth;
        }
        if (top <= 0) {
            top = 0;
        } else if (top >= this.clientHeight - this.ele.offsetHeight) {
            top = this.clientHeight - this.ele.offsetHeight;
        }
        this.ele.style.left = left + "px";
        this.ele.style.top = top + "px";
    }
}

const box2 = document.querySelector(".box2");
const test2 = new Drag2(box2);
console.log(test2);

闭包

是一个定义在一个函数内部的函数

函数嵌套时,利用作用域的嵌套,将原本的局部变量变成私有变量的方式(内部函数调用外部函数的局部变量,那么这个时候,这个局部变量就会变成内部函数的私有变量)

闭包的原理
函数的词法作用域

  • 函数的定义作用域:函数被定义的地方
  • 函数在执行时,可以使用自身词法作用域中的数据(变量)

闭包的应用

  • 循环中的事件处理函数内,使用循环每次执行到的计数器
  • 可以给系统功能的不能传参的回调函数传参
  • 可以给“事件处理函数”传参

实现调用函数累加的效果

const test = (function fn(){
    let a=0;
    // 将函数f作为返回值给函数fn,函数fn再执行然后作为test的执行结果
    return function f(){
        a++;
        console.log(a);
    }
})()

console.log(test)
test()
test()
test()

function f2(){
    const aa=1;
}
console.log(f2)

用闭包实现点击当前对象的效果

html

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

js

const liList = document.querySelectorAll("li");

for (var i = 0; i < liList.length; i++) {
    liList[i].index = i;
    liList[i].onclick = function () {
        console.log(this.index);
    }
}

// 通过闭包实现点击
for (var i = 0; i < liList.length; i++) {
    // 把功能放入一个匿名函数体中,自动执行
    (function (i) {
        liList[i].onclick = function () {
            console.log(i);
        }
    })(i);
}

for (var i = 0; i < liList.length; i++) {
    // 把i放入函数f1中作为函数f2的返回值给f2,点击函数再执行f2
    liList[i].onclick = (function f2(i) {
        return function f1() {
            console.log(i);
        }
    })(i);
}

// 用let关键字触发词法作用域
for(let i=0;i<liList.length;i++){
    liList[i].onclick=function(){
        console.log(i);
    }
}

实现延时器的效果

setTimeout(test("test"), 2000);
// 这样写会直接执行,延时器没有作用
function test(msg){
    console.log(msg);
}

// 闭包,将函数test01作为返回值给函数test,将来执行的时候执行test01内的语句
function test(msg) {
    return function test01() {
        console.log(msg);
    }
}

闭包的特点

  • 可以在作用域外部操作作用域内部的变量
  • 可以读取函数内部的变量
  • 内部和外部沟通的桥梁
  • 让这些变量的值,始终保存在内存中,不会在调用结束后被系统回收,避免全局变量命名空间的污染
  • 消耗性能
  • 闭包有可能会造成内存泄漏(低版本IE8-)
  • 小心使用

设计模式

设计模式是一种可以复用的解决方案,是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结

1. 单例模式

  • 单个实例
  • 单例模式 的 弹出框
  • 通过手动模拟 new 的原理,实现单例模式

2. 观察者模式(发布订阅者)

  • 发布:被观察者,主题对象
  • 订阅:观察者
  • 一个主题对象发布或更新信息,多个订阅者接收信息,并根据信息作出不同的功能处理
  • 可以实现广播通信,一对多关系,耦合低

3. 适配器模式

  • 适配器
  • 假如现有数据A,和功能B,功能B只能接受B类型的数据,可是现有的数据类型是A
    • 将数据A改成B类型的数据 x
    • 将功能B接受的数据类型改成A类型 x
  • 此时需要一个适配器,将数据A进行一层包装,让数据A看起来像,B类型的数据

4. 代理模式

  • 代理
  • 系统功能A在调用系统功能B的过程中,传输了数据,我们需要记录数据,或改写数据,或拦截数据
  • 先断开执行,获取系统功能B的执行权限,编写代理程序执行功能B,让功能A调用代理程序,将原有的数据,发给代理程序,代理程序将数据发给功能B

5. 策略模式

  • 策略,计划
  • 根据程序执行过程中产生的不同的状态或信息,决定后续的功能执行
  • 利用不同的功能接口(方法)决定执行不同的功能

6. 组合模式

  • 按照一定的组织关系,将多个对象进行组合
    • 树状结构(html结构)
  • 组合模式就是为动态的html而生的
  • 组合模式为了能够实现批量操作,节省操作过程,使用了递归思想,所以消耗比较多的性能
  • 利用组合器将对象组合起来
    • 枝对象:只有具有子对象,无论层级在哪,都是枝对象
    • 叶对象:只有不具有子对象,无论层级在哪吗,都是叶对象

7. 抽象工厂模式

  • 抽象
  • 工厂
  • 在工厂模式的继承之上,再次对同一个实例的相同属性进行抽象,抽象成一个公共对象,在做具体的工厂模式的创建

8. MVC模式

  • M:model:模型层,只负责数据的管理
  • V:view:视图层,只负责将来数据展示的视图的管理
  • C:control:控制器层,负责接收用户的指令,根据指令,选择不同的模型,将模型中的数据,加给不同的视图渲染
  • 工作流程:
    • 控制器接收到指令后,根据指令读取指定的模型,拿到数据
    • 控制器再根据指令获取指定的视图
    • 将第一步读取到的数据,传给获取到的视图
    • 由视图负责将接收到的数据,渲染
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 13:59:39  更:2021-09-27 14:01:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:26:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码