JS高级

1、面向过程 / 面向对象

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。   冰箱打开->大象进去->冰箱关闭

优点︰性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。

缺点:没有面向对象易维护、易复用、易扩展

 

面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。    大象:1进去;冰箱:2打开、3关闭:  2->1->3

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

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵淞更加易于维护

缺点∶性能比面向过程低

 

2、ES6中的类和对象

面向对象的思维特点:

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

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

面向对象编程我们考虑的是有哪些对象,按照面向对象的思维特点,不断的创建对象,使用对象指挥对象做事情

 

在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。对象由属性和方法构成。
ES6中类没有变量提升,所以必须先定义类,然后再实例化。类里面共有属性和方法都要加this指向类内

 

3、创建类/封装

        class Star {           //构造
            constructor(uname) {
                this.name = uname;    //this指向实例对象ldh
            }
       say(song){
          console.log(this);      //这里this指向调用者ldh           console.log(
song);        } } var ldh = new Star('ldh'); //new调用 console.log(ldh);       ldh.say('by');

 

4、继承

        class F {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);
            }
        }
        class S extends F {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
        }
        var ldh = new F(1, 2);
        ldh.sum();
        var zxy = new S(1, 2);
        zxy.sum();           //调用父类内的子类时,其this的指向为子类constructor,调用的方法采用就近原则,先搜索子类内有无,在搜索父类。此处的this指向为父类,会报错

修订后的子类:
class S extends F {
            constructor(x, y) {
                super();    //super调用父类constructor。若想拓展子类,即子类有父类属性,也有自己属性,得先super父类,再设置自己的属性    
          this.x = x;
          this.y = y;   //先super父类才不会报错 }
      say(){
         super();   //也可调用父类的函数
      } }

 

5、ES5中构造函数和原型

  A、构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

new在执行时会做四件事情:
  1、在内存中创建一个新的空对象。
  2、让this指向这个新的对象。
  3、执行构造函数里面的代码,给这个新对象添加属性和方法。
  4、返回这个新对象(所以构造函数里面不需要return )。

 

  B、构造函数内成员

  1、构造函数内的实例成员是通过this添加的成员,只能由实例化的对象来访问。

  2、在构造函数本身添加的成员叫静态成员,只能用过构造函数访问;

 

  C、构造函数:浪费内存,不同对象相同方法需要开辟不同的新内存空间;

解决方法:prototype。JavaScript规定,每一个构造函数都有一个prototype属性指向另一个对象。注意这个prototype就是一个对象,这个对象的所有属性和方法都会被构造函数所拥有,共享

方法一般放到原型对象内

        class Star {       
            constructor(uname) {
                this.name = uname;  
            }
        }
        
        Star.prototype.say = function(song){    //共享方法
          console.log(song);
       }

对象有对象原型__proto__:

对象都会有一个属性__proto_指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方沙,就是因为对象有_proto_原型的存在。先看对象内有无,没有再去prototype

 

  D、对象原型(__proto__)和构造函数( prototype )     原型对象里面都有一个constructor属性,constructor我们称为构造函数,因为它可以指回构造函数本身。有时会手动指回

        class Star {       
            constructor(uname) {
                this.name = uname;  
            }
        }
        
        Star.prototype = {
        constructor: Star, //重新指回构造函数Star,如果没有这句,在调用下面两函数的时候指针会指向对象Object,而不是指向Star say:
function(song){ //共享方法           console.log(song);        } said: function(){           console.log(1);        } }

 

构造函数、实例、原型对象之间的关系              原型链(注意,其实function也有其原型):

 

 

 

6、成员查找

当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。如果没有就查找它的原型(也就是_proto_指向的prototype原型对象)。如果还没有就查找原型对象的原型( Object的原型对象)。

依此类推一直找到Object为止 ( null )。_proto_对象原型的意义就在于为对象成员查找机制提供一个方向,或者说─条路线。

 

7、扩展内置对象

通过原型对象,对原来的内置对象进行自定义方法扩展,如对数组增加求和方法等

注意∶数组和字符串内置对象不能给原型对象覆盖操作Array.prototype = {},只能是Array.prototype.xxx= function(){}的方式。

 

8、ES5组合继承:构造函数+原型对象

  1、call() 调用函数

function fn(){
  console.log(this);      //指向object,没人调用
}
fn.call();

  call改变this指向

    function fn() {
            console.log(this);    //指向o
        }
        var o = {
            name: 2
        }
        fn.call(o,1,2);  //第一个参数改变this指向,不参与形实转换

  2、利用call把父类this指向子类,从而完成继承

        function Father(uname, age) {
            this.name = uname;
            this.age = age;
        }

        function Son(uname, age) {
            return Father.call(this,uname,age);     //父类指向子类uname,age
        }
        var son = new Son('jacky',18);
        console.log(son);

   3、子类继承后,当需要修改子类方法且不影响父类方法时,需要实例化一个对象充当中间件,若直接子类原型对象等于父类原型对象,这是把地址赋值,当子类变换时,地址内容变换,则父类变换

        function Father(uname, age) {
            this.name = uname;
            this.age = age;
        }
        Father.prototype = {
            // constructor:Father,    //对方法继承无效
            money:function(){
                console.log(10000);
            }
        }

        function Son(uname, age) {
            return Father.call(this,uname,age);
        }
        
        // Son.prototype = Father.prototype;  //对方法继承有效,但是该方式为直接的地址赋值,若子的内容修改,父也将修改,即父类也有exam
        Son.prototype = new Father();     //新建中间件实例对象
        Son.prototype.constructor = Son;   //利用对象修改了Son后需要用constructor指回原对象
        Son.prototype.exam = function(){
            console.log(100);
        }
        var son = new Son('jacky',18);
        console.log(son);                             //有exam
        console.log(Father.prototype);          //无exam

 

9、ES5新增方法

  1、数组

迭代(遍历):

遍历:无返回值 forEach(function(currentValue,index,arr));    有返回值 map(function(currentValue,index,arr));   

筛选:返回数组 filter(function(currentValue,index,arr));   

判断:返回布尔值  some(function(currentValue,index,arr)) 找到即停止,或;    every(function(currentValue,index,arr))全部遍历且满足,与;   

注意,some下需要return true; 当找到后跳出,才能提高效率,否则会一直遍历,效率不高,和forEach没区别

  2、字符串

str.trim(); 删除字符串的两端空白字符串,返回新字符串,不影响原字符串。可用在表单验证处,删除开头空格

  3、对象方法

Object.keys(obj); 获取对象自身所有属性,类似for...in...,返回一个属性名组成的数组

  Object.defineProperty(obj, prop, descriptor); 定义新属性或修改原属性

  descriptor说明:以对象形式{}书写:

    value:设置属性的值默认为undefined

    writable:值是否可以重写。true | false 默认为false

    enumerable:目标属性是否可以被枚举遍历。true | false 默认为false

    configurable:目标属性是否可以被删除或是否可以再次修改特性true | false 默认为false

 

10、函数进阶

  1、函数定义:

    1.1:函数声明function(命名函数function fn、匿名函数var fn  = function、new Function(参数1, 参数2, 函数体)  函数也属于对象

  

 

     1.2:函数的调用:普通函数、对象的方法、构造函数、绑定事件函数、定时器函数、立即执行函数

   2、this指向,一般指向调用者。但也可以手动改变,bind(), call(), apply()

  

    2.1:call(指向对象,参数1,参数...)   可以调用函数,可以改变函数内this指向,主要用来实现继承

    2.2:apply(指向对象,参数数组)   可以调用函数,可以改变函数内this指向,传递数组,可以用来处理数组有关的数据,如数学Math内置对象使用,求最大值

Math.max.apply(null, arr)    //null意思为不需要指向
var max = Math.max.apply(Math, arr)  //此处指回Math

    2.3:bind(指向对象,参数1,参数...)  不调用函数,所以返回值是一个改造this指向和参数后的原函数拷贝,多用于需要改变this指向且不需要立即调用的地方

var o = {
  name: 'Jakcy';  
}
function fn(){
  console.log(this);  
}

var f = fn.bind(o);  //并不会直接执行,只是对其一个改变this的拷贝
f();  //加上才能执行
    btn.onclick = function () {
        this.disabled = true;
        // var that = this;   //传统用中间变量保存this,但会造成空间浪费
        setTimeout(function () {
            // that.disabled = false;
            this.disabled = false;
        // }, 3000)
        }.bind(this), 3000)   //此处函数绑定this,即btn,且不立即调用,还是由定时器管控
    }

  3、严格模式(IE10)   为整个脚本或者某一函数开启严格模式 use strict

    1.消除了Javascript语法的一些不合理、不严谨之处,减少了一些怪异行为。

      1.如变量必须规定、2.不能随意删除声明好的变量、3.全局函数this不指向window,而为undefined(定时器还是window)、4.因为undefined,所以构造函数必须new使用、5.函数不许有重名参数、6.函数要声明在函数代码块(js初始即为一个立即执行函数),不允许在非函数代码块(if, for)下声明

    2.消除代码运行的一些不安全之处,保证代码运行的安全。

    3.提高编译器效率,增加运行速度。

    4.禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的Javascript做好铺垫。比如一些保留字如: class, enum, export, extends, import, super不能做变量名

 

  4、高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。典型例子callback&&callback(); 

 

  5、闭包( closure )指有权访问另一个函数作用域中变量的函数,可以定义为一个函数内部的函数

作用域:局部变量和全局变量

  1.函数内部可以使用全局变量。

  2.函数外部不可以使用局部变量。

  3.当函数执行完毕,本作用域内的局部变量会销毁。

function fn(){       //此处fn为闭包,被访问变量所在的函数为闭包
  var num = 10;
  funciton fun(){
       console.log(num); 
    }  
 return fun; //返回一个fun,即var f接回一个fun函数,fun可以访问fn的num,所以f也可访问num } var f = fn();
f(); //外部访问num, 这一步我个人理解就是fun延迟执行了

 常见闭包点击面试题:

    var li = document.querySelectorAll('li');
    for (var i = 0; i < li.length; i++) {
        console.log(i);
        (function(i){         //立即执行函数也称小闭包
            li[i].addEventListener('click',function(){
            console.log(i);
        })
        })(i);
    }

 

  6、递归:一个函数在内部调用自身。递归容易像循环一样产生死循环,称为栈溢出,所以需要加退出条件

 

  7、深浅拷贝:

    1.浅拷贝只是拷贝一层,更深层次对象级别的拷贝地址,如果修改拷贝对象的话,会将源对象修改

    2.深拷贝拷贝多层,每一级别的数据都会拷贝

    3. Object.assign( target, ..sources)  es6新增方法可以浅拷贝

 

  8、正则表达(Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。

    三大功能:匹配、替换、提取

    JS中:1、调用RegExp对象的构造函数创建;2、通过字面量创建。(可以用     regexobj.test (str)     检测是否符合表达规范)

    正则表达符号:边界符^$、字符类[ ]  (中括号里有^即取反)、范围符 - 、量词符 * + ? {n} {n,} {n,m}、预定义类 \d \D \w \W \s \S等、或者  |  (一个竖线)

    替换:stringObject.replace(regexp/substr,replacement)  返回值为新字符串

    /表达式/[switch] :匹配模式:g(全局匹配)、i(忽略大小写)、gi:(全局匹配+忽略大小写) 

    字符串的正则方法有match()、replace()、search()、split()

 

    正则对象的方法有:exec()、test()

 

 

posted @ 2021-08-29 22:48  Jacky02  阅读(160)  评论(0)    收藏  举报