前端知识点汇总。一

前端知识点汇总:

1.js的闭包

  • 闭包的3个特性:

    函数嵌套函数
    函数内部可以引用函数外部的参数和变量
    参数和变量不会被垃圾回收机制回收
    上面三局话啥意思? 其实个人感觉有点绕,用代码解释比较简单。

    ///方法aaa中定义了一个变量name,name等于 “1111”。定义了一个函数 function()(此处函数嵌套函数)
    function aaa(){
        var name = "1111"
        return function(){
    		//此处name 引用了它外部的变量。
            return name
        }
    };
    var b = aaa();
    //运行b(),返回出来了name,说明这边的name并没有被垃圾回收。
    b();
    
  • 闭包的作用
    其实上面说的特性就已经表明了闭包的作用。那我们再看一段代码来巩固一下。

  • function aaa(){
        var num = 0
        return function(){
            return ++num
        }
    };var b = aaa();b();b();b()
    

    此处输出值应该是多少?

  • 常见场景

    我们知道的闭包的特性,那我们的应该用这个闭包来做什么呢?。在哪些场景会用到呢?

    在这么一个场景:客户进入页面我们就要提醒他,他今天操作了多少条单据了,大于多少条他就可以收工回家了。
    那我们在他每次操作完单据,就给他触发一次方法。
    示列代码:

    function  gohome(){
        var twice = 0
        return function(){
            return ++twice ;
        }
    }; var b = gohome();b()
    

    突然,客户说,哎呀 我想自己填一个数值进去,你这计算的不一定准确,或者说他想早点下班。

    那我们最后写成的需求就是:

    function  gohome(){
        var twice = 0;
        return function(x=0){
            if(x === 0)
                return ++twice ;
           return twice = twice + x;     
        }
    }; var b = gohome();b(100) //可以复制到控制台自行打印
    

    突然,客户又说,哎呀。我不想一次加一个 ,我想一次加10个!并且我要从1000开始算! 这样领导以为我干活认真!好,那就走起

    function  gohome(start,times){
        var twice = start;
        return function(x=0){
            twice = times + twice +x;
            return twice ;
        }
    }; var b = gohome(1000,10);b()//可以复制到控制台自行打印
    

    思考:那闭包一定就好吗? 并不是,闭包只有在全局事件中会使用,因为闭包事件并不会释放内存,会导致内存升高,最终会导致内存泄露,所以不能乱用。

2.js的原型链

  • 什么是原型链?

    //控制台输出
    function Person(age)
    {    
    this.age = age 
    } 
    Person.prototype.name2 = 'gogogo' 
    //prototype就是Person的原型链
    Person.prototype
    
    

    突然感觉网上讲的比我好多啦,抄张图。

image-20220329152922764

开局一张图...对于这方面的理解。。小的技术还不够深入,懂,但是不知道怎么用。。。但是!总结了一些他们之间相互获取的方法,作为记录防止以后用到。

function AAA(){}
var a = new AAA();
a.__proto__ === AAA.prototype;
AAA.prototype.constructor ===  AAA;

3.js的继承

继承的实现方式:

首先定义一个父类:

function Person(name){
    this.name = name;
    this.sum = function(){
        return this.name;
    }
}
Person.prototype.age = 10
  1. 原型链继承
    原理:新建一个对象,再让他的原型等于Person,等于他继承了Person
    代码示列:

    function Per(){
        this.name = 'ker';
    }
    Per.prototype = new Person();
    var per1 = new Per();
    per1.age //10
    per1.sum() // ker
    var per2 = new Per();
    //一个实例修改了原型属性,另一个实例的原型属性也会被修改
    per1.__proto__.name = 'ker3';
    per2.__proto__.name // 'ker3';
    //新实例无法向父类构造函数传参
    var per3 = new Per('ker4');
    per3.name //ker
    

    重点:让新实例的原型等于父类的实例。
        特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
        缺点:1、新实例无法向父类构造函数传参。
           2、继承单一。
           3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

2.构造函数继承

​ 原理:用.call()和apply()将父类构造函数引入子类函数(在子类函数做父类函数自执行)
call和apply的作用(改变自身的this指向,)--作用一样,只是用法不一样。

(课外知识,bind(),可以百度搜搜,这三个方法实现了方法与方法之间的借用,很不错。同样的,继承的原理就是借用。看到这边你没有想到Bind()的作用和我们写的代码很像? ()=> 你可以理解为这个就是bind())

代码示列:
function Person2(name2){
    this.name2 = name2;
    this.sum2 = function(){
        return this.name2 +"我是第二个";
    }
}

function Con(name){
    //在子实例中可向父实例传参
    Person.call(this,name);
    //可以继承多个构造函数属性(call多个)
    Person2.call(this,name);
    this.age = 12;
}
//
var con1 = new Con('jer11');
con1.name //jer11
con1.name2 // jer11
con1.sum2() // jer11我是第二个
var con2 = new Con('jer22');
//这边俩个方法俩个不相同的方法,所以叫做不能复用。
con2.sum2() === con1.sum2() false

​ 特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。

       2、解决了原型链继承缺点1、2、3。
       3、可以继承多个构造函数属性(call多个)。
       4、在子实例中可向父实例传参。
    缺点:1、只能继承父类构造函数的属性。
       2、无法实现构造函数的复用。
       3、每个新实例都有父类构造函数的副本,臃肿。

3.原型链继承+构造函数继承(组合继承,常用)

function LiuXXX(name){
    Person.call(this,name);
}
LiuXXX.prototype = new Person();
var xiaoliu = new LiuXXX('liuxiao');
xiaoliu.name // liuxiao
xiaoliu.sum()// liuxiao

优点:结合了两种模式的优点,传参和复用
缺点:父类方法调用了两次, 而且不能判断实例的构造函数是子类还是父类

其实到这边差不多了,后面还有寄生继承,原型寄生继承,寄生组合继承(常用),大家可以去了解一下。 这边大概就是js的一些基础。下面我们就会讲到我们常用的一些方法和语法。

4.es5与es6的不同,es6重要的特性.

es5 和es6的不同,或者说es6比es5多了哪些东西?

  • export : 每次我们在写js代码时,都会有一个 export.... 或者 export defalut 。其实这就是es6的语法。这是es6将每个js文件都模块化了。大家有个概念就好。代码演示:

    //xxx.js
    var x = 1;
    var y = 2;
    var z = 3;
    export {x,y,z}
    //llll.js
    import {x,y,z} from xxx.js
    //按需加载
    require('路径名+文件名');
    //异步加载文件
    const main = document.querySelector('main');
    import(`./section-modules/${someVariable}.js`)
      .then(module => {
        module.loadPageInto(main);
      })
      .catch(err => {
        main.textContent = err.message;
      });
    
    
  • let const var 的区别

    话不多说 上代码。

    var a = 1;
    var a = 2;
    a   // 2
    var  a = 1;
    var a;
    a  // 1
    
    const a = 1;
    const a;
    //  Uncaught SyntaxError: Identifier 'a' has already been declared
    
    let a = 1;
    let a ;
    a  // undefined
    let a = 1 ;
    let a = 2;
    a  // 2;
    
  • 一些操作对象的简单方法

    Object.assign();
    //这个方法不会复制getter和setter
    //后面一个对象会覆盖前面一个对象 如果值一样;
    const target = { a: 1, b: 1 };
    const source1 = { b: 2, c: 2 };
    const source2 = { c: 3 };
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    
    //这个方法是一个浅拷贝,对于对象中的对象无法进行复制,只会丢失。
    const DEFAULTS = {
      url: {
        host: 'example.com',
        port: 7070
      },
    };
    
    processContent({ url: {port: 8000} })
    // {
    //   url: {port: 8000}
    // }
    Object.assign();//一般和 ...list 合起来用
    
    
    Object.key(obj);//获取对象属性名的数组
    Object.values(obj);//获取对象值的数组;
    
    
    
  • Proxy 拦截器

    这个东西很深入,用法很多。先看代码

    let target = {
        name: 'Tom',
        age: 24
    }
    let handler = {
        get: function(target, key) {
            console.log('getting '+key);
            return target[key]; // 不是target.key
        },
        set: function(target, key, value) {
            console.log('setting '+key);
            target[key] = value;
        }
    }
    let proxy = new Proxy(target, handler)
    proxy.name     // 实际执行 handler.get
    proxy.age = 25  
    

    proxy 拦截了target的动作,对应动作。
    get:属性的读取。可以被继承。

    set:属性的赋值。
    apply:拦截函数的调用。

    代码示列:

    get :
    const proxy = new Proxy({}, {
       //目标,目标key,原始的操作行为所在的那个对象,一般是proxy实例
      get: function(target, key, receiver) {
    //TO DO
      }
    });
    
    const d = Object.create(proxy);
    d.a === d // true
    
    set:
    const handler = {
        //set必须要返回true,否则报错
        //分别对应目标,目标key,传入值,原始的操作行为所在的那个对象,一般是proxy实例
      set: function(obj, prop, value, receiver) {
        obj[prop] = receiver;
        return true;
      }
    };
    const proxy = new Proxy({}, handler);
    proxy.foo = 'bar';
    proxy.foo === proxy 
    
    
    apply:
    var target = function () { return 'I am the target'; };
    var handler = {
        //分别对应目标,目标的上下文(this),参数
      apply: (target,ctx,args) {
        return 'I am the proxy';
      }
    };
    var p = new Proxy(target, handler);
    p()
    

    Proxy 对象可以拦截目标对象的任意属性,这使得它很合适用来写 Web 服务的客户端。

    const service = createWebService('http://example.com/data');
    
    service.employees().then(json => {
      const employees = JSON.parse(json);
      // ···
    });
    

    上面代码新建了一个 Web 服务的接口,这个接口返回各种数据。Proxy 可以拦截这个对象的任意属性,所以不用为每一种数据写一个适配方法,只要写一个 Proxy 拦截就可以了。

    function createWebService(baseUrl) {
      return new Proxy({}, {
        get(target, propKey, receiver) {
          return () => httpGet(baseUrl + '/' + propKey);
        }
      });
    }
    

    后端的proxy代理也是这个原理。

  • Promise!Promise!Promise!

    重要的事情说三遍~
    先看代码

    //基础用法
    let promise = new Promise(function(resolve,reject){
        //your code
        if(/*action success*/)
           resolve(value);//value是你操作成功后想传给后面的值
    	else
    		reject(error);//一般抛错,或者传出错误信息;
    });
    //列子
    function timeout(ms){
        return new Promise((resolve,reject)=>{
            setTimeout(resolve,ms,'done')
        })
    }
    timeout(100).then(res=>{
        console.log(res);
    })
    //用promise实现aynsc
    function getJson(url){
        const getData = new Promise((resolve,reject)=>{
            
        })
        
    }
    
  • 解构赋值

    var foo = ["one", "two", "three", "four"];
    var [one, two, three] = foo;
    console.log(one); // "one"
    console.log(two); // "two"
    console.log(three); // "three"
    
  • 延展操作符

    代码:

    //数组拷贝
    var arr = [1, 2, 3];
    var arr2 = [...arr]; // 等同于 arr.slice()
    arr2.push(4); 
    console.log(arr2)//[1, 2, 3, 4]
    //构造数据
    const stuendts = ['Jine','Tom']; 
    const persons = ['Tony',... stuendts,'Aaron','Anna'];
    conslog.log(persions)// ["Tony", "Jine", "Tom", "Aaron", "Anna"]
    //函数调用
    function sum(x, y, z) {
      return x + y + z;
    }
    const numbers = [1, 2, 3];
    
    //不使用延展操作符
    console.log(sum.apply(null, numbers));
    
    //使用延展操作符
    console.log(sum(...numbers));// 6
    
posted @   呢喃emmmmmm  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示