• Java_Script函数作用域,结构及数组、对象操作


    javascript 是一种基于原型(prototype)的面向对象的语言,而不是基于类的面向对象语言
    C++,Java 有Class和实例 Instance 的概念,类是一类事物的抽象,而实例则是类的实体
    JS是基于原型的语言,它只有原型对象的概念,原型对象就是一个模板,新的对象从这个模板构建从而获取最初的属性,任何对象在运行时可以动态的增加属性,而且,任何一个对象都可以作为另一个对象的原型,这样后者就可以共享前者的属性、
     
    数组的解构
    const arr =[100,200,300];
     
    let [x,y,z] = arr;
    console.log(1,x,y,z);
    //100,200,300
     
    //丢弃
    const [,b,] = arr;
    console.log(2,b);
    // 200
     
    //变量与元组个数不匹配
    const [d,e ]= arr;
    console.log(3,d,e);
    //100 200
     
    const [m,n,o,p] =arr;
    console.log(4,m,n,o,p);
    //100 200 300 undefined
     
    //可变变量
    const [f,...args] = arr;
    console.log(5,f,args);
    // 100,[200,300]
     
    //支持默认值
    const [j=1,k,,,l=10] = arr;
    console.log(j,k,l);
    //100 200 10
     
    解构时,变量从左到右和元素对齐,可变参数放到最右边
    能对应到数据就返回数据,对应不上就返回默认值,没有默认值就是undefined
     
    对象的解构
    const obj = {
        a:100,
        b:200,
        c:300
    };
     
    let {x,y,z} = obj;
    console.log(1,x,y,z);
    //undefined undefined undefined
     
    let {a,b,c} = obj ;
    console.log(2,a,b,c);
    // 100 200 300
     
    let {a:m,b:n,c:p} = obj;
    console.log(3,m,n,p);
    // 100 200 300
     
    let {a:M,b:N,c:C='Python',d:D='hello'} = obj;
    console.log(4,M,N,C,D);
    // 100 200 300 'hello'
     
    数组的操作
     
                      方法
                                                                描述
    push(...items)
    尾部增加多个元素
    pop()
    移除最后一个元素,并返回它
    map
    引入处理函数来处理数组中的每一个元素,返回新的数组
    filter
    引入处理函数处理数组中每一个元素,此处理函数返回true的元素保留,否则该元素被过滤掉,保留的元素构成新的数组返回
    foreach
    迭代所有元素无返回值
     
    对象的操作
     
                                         Object的静态方法
                                                             描述
    Object.keys(obj)
    ES5开始支持,返回所有key
    Object.values(obj)
    返回所有值,试验阶段,支持较差
    Object.entries(obj)
    返回所有值,测试阶段,支持较差
    Object.assign(target,...sources)
    使用多个source对象,来填充target对象,返回target对象
     
    const obj = {
        a:100,
        b:200,
        c:300
    };
     
    console.log(Object.keys(obj));
    console.log(Object.values(obj));
    console.log(Object.entries(obj))
     
     
     
    定义类
         字面式声明方式
              var obj = {
                             property_1 : value_1,
                             property_2 : value_2,
                             ......
                             "property n" : value_n
                             };
    这种方法也称作字面值创建对象
     
    ES6之前的实现
         定义一个函数(构造数)对象,使用this 定义属性
         使用new和构造器创建一个新对象
          //定义类
         function Point(x,y) {
        this.x = x;
        this.y = y;
        this.show = () => {
            console.log("this:",this,this.x,this.y)
        }
    }
          // 继承
          function Point3D(x,y,z) {
             Point.call(this,x,y);
             this.z = z;
             console.log(this,z);
              }
    console.log(Point3D);
    p2 = new Point3D(13,14,15);
    console.log(p2);
    p2.show()
     
    new 构建一个新的通用对象,new操作符会将新对象的this值传递给Point3D构造器函数,函数为这个对象创建Z属性
    从上句话知道new后得到一个对象,使用这个对象的this来调用构造器,那么如何执行“基类”的构造器方法呢?使用Point3D对象的this来执行Point构造器,所以使用call方法,传入子类的this
     
    ES6中的class
         从ES6开始,新提供了 class关键字,使得创建对象更加简单,清晰
         1、类定义
               使用class关键字,创建的本质上还是函数,是一个特殊的函数
         3、一个类只能拥有一个constructor的构造器方法,如果没有显式定义一个构造一个方法,则会添加一个默认的constructor方法
         4、继承使用extends关键字
         5、一个构造器可以使用super关键字来调用一个人父类的构造函数
         6、类没有私有属性
    示例:
    class example {
              constructor /*consturctor =>构造器函数*/(args1,args2){
                   this.args1 = args1;
                   this.args2 = args2;
                   // this is what mean?  like python class self~~~
                   }
              show() /* this show function is from example_class definition */
                        {
                   console.log("hello world")
                        }
    how to use this class?
         take new definition to this class
         like: 
              Point = new example(args1,args2)
     
    use inherit(继承)
     
    class Point3D extends Point{
        constructor(x,y,z){
            super(x,y);     //只是继承父类的this.x = x ,this.y = y 方法
            this.z = z;
        }
        show(){
            console.log(this.z,this.x,this.y)
        }
    }
     
    let P2 = new Point3D(1,2,6);
    P2.show();
     
    重写方法
         直接子类中重写一个 父类的方法,即可调用子类的 重写方法
         箭头函数也支持子类的覆盖
         如果想使用父类的方法,使用super.method()的方式调用即可
         
    总结:
         父类,子类使用同一种方式类定义方法,子类覆盖父类
         如果父类使用属性,子类使用方法,则使用父类的属性,如果父类使用方法,子类使用属性,则使用子类的方法, 优先使用属性
     
     
    静态属性
         静态属性目前还没有得到很好的支持
        
    静态方法
         在方法名前 加上static  就是静态方法了
         class add{
         constructor(x,y){
         this.x = x 
         this.y = y
          }
         static show (){
              console.log("this is show function")
    }
     
    静态方法不需要实例调用,所以也不需要self 与cls, 直接使用类直接调用即可,like==> add.show()
         静态方法,实例不能直接访问,
         实例 可以通过 构造方法访问,like  ==> add.constructor.show()
     
    #静态的概念和python中的静态不同,相当于python中的类变量
     
     
    关于this的知识点
         js是动态语言,在运行期绑定,this在编译期绑定
         var school = {
             name : 'magedu',
             getnamefunc : function () {
                 console.log(1,this.name);
                 console.log(2,this);
                 return function () {
                     console.log(3,this == global);
                     return this.name
            }
        }
    };
     
    console.log(school.getnamefunc());
    console.log(school.getnamefunc()());
     
    1、函数执行时,会开启新的上下文环境ExecutionContext
    2、创建this属性,但是this是什么就要看函数是怎么调用的了
    3、使用 school.getnamefunc() () ,调用,普通函数school.getnamefunc()( )调用方式,this指向global对象,nodejs的global或者浏览器的window
                school.getnamefunc() 对象的调用方式,this指向包含该方法的对象
     
    4、call和apply方法调用,需要注意第一个参数是谁
     
    如何避免 this指针带来的不便呢?
    1、显示传入(主动传入一个对象)
         var school = {
             name : 'magedu',
             getnamefunc : function () {
                 console.log(1,this.name);
                 console.log(2,this);
                 return function (that) {
                     console.log(3,that == global);
                     return that.name
            }
        }
    };
     
    // console.log(school.getnamefunc());
    console.log('~~~~~');
    console.log(school.getnamefunc()(school));
    //在调用时,将对象显示的传入进去,这样类似于绑定方法
     
     
    2、ES,引入了apply,call方法
         var school = {
             name : 'magedu',
             getnamefunc : function () {
                 console.log(1,this.name);
                 console.log(2,this);
                 return function () {
                     console.log(3,this == global);  //判断当前this是否是全局的
                     return this.name
            }
        }
    };
     
    // console.log(school.getnamefunc());
    console.log('~~~~~');
    console.log(school.getnamefunc().call(school));
    //call方法显示的传入了this对应的对象,确保了程序执行的正确性
    apply call 方法都是函数对象的方法。第一参数都是传入对象引入的
     
    function Print(){
        this.print = function (x,y) {console.log(x+y)
        };
    }
    p =new Print();
    p.print(10,20);
     
    call传其他参数需要使用可变参数收集
    p.print.call(p,10,20);
     
    apply传其他参数需要使用数组
    p.print.apply(p,[10,20]);
     
    ES5引入了bind方法
         bind方法来设置函数的this值
         var school = {
             name : 'school',
             getNamaefunc : function () {
                 console.log(this.name);
                 console.log(this);
                 return function () {
                     console.log(this == global);
                     return this.name;
            };
        }
    };
     
    var func = school.getNamaefunc();
    console.log(func);
    console.log('~~~~~~~~~~');
    var boundfunc = func.bind(school);          //绑定后返回新的 函数bound()
    console.log('~~~~~~~~~~');
    console.log(boundfunc);
    console.log('~~~~~~~~~~');
    console.log(boundfunc());
     
    apply,call方法、参数不同,调用时传入this
    bind方法是先绑定this,调用时直接传入
     
    ES6 引入支持this的箭头函数
         ES6新技术,不需要兼容this问题
         class school{
             constructor(){
                 this.name = 'magedu'
             }
             getNamefunc(){
                 console.log(this.name)
                 console.log(this,typeof this)
            return () =>{
                     console.log(this == global);
                     return this.name;
            };
        }
    }
     
    console.log(new school().getNamefunc()());
     
    bind方法在应用中使用的较多
     
    高阶对象,高阶类,或称为Mixin模式
         Mixin模式,混合模式这是一种不用继承就可以复用的技术,主要还是为了解决多重继承的问题,多继承路径是个问题
         js是基于对象的,类和对象都是对象模板
         混合mixin,指的是将一个对象的全部或者部分拷贝到另一个对象上去,其实就是属性
         可以将多个类或者对象混合成一个类或对象
     
    继承实现实例:
    class Serialization{
        constructor(){
            console.log('Serialization constructor~~~')
            if (typeof(this.stringfy)!== "function") {
                throw new ReferenceError('should defined stringfy');
            }
        }
    }
    class Point extends Serialization{
        constructor(x,y){
            console.log("point constructor")
            super();
            this.x = x
            this.y = y
        }
         //子类必须满足继承父类的构造器函数条件才可以完成构造,所以子类中需要一个stringfy方法
        stringfy (){
            return `<Point ${this.x}.${this.y}>`
        }
    }
     
    //Point类继承了父类的构造器方法,父类构造器中方法条件不满足则构造失败
    // s = new Serialization();
    p = new Point(4,5);
     
     
    //高阶类的实现
     
    class A extends Object{};
    console.log(A);
     
    //匿名继承
    const B = class extends Object{
        constructor(){
            super();
            console.log('B constructor');
        }
    };
    // console.log(B);
    // b = new B();
    // console.log(b);
     
    //箭头函数,参数是类,返回值也是类
    const x =(sup) => {
        return class extends sup{
            constructor(){
                super();
                console.log('b constructor');
            }
        }
    }
     
    //演化
    const C = sup => class extends sup{
        constructor(){
            super();
            console.log("c constructor")
        }
    }
     
    cls = C(A);
    console.log(cls,typeof cls);
    c = new cls();
    console.log(c);
    //流程, 定义常量C,它是一个函数,这个函数可以混合别的类返回一个新的类new class = C(需要混合的类名),拿到new class后,在对其实例化    cls  = new class();, 这样生产出的 cls类就可以获得 混合类的属性与方法
     
    将序列化函数改造为箭头函数 高阶对象实例
    const Serialization = Sup => class extends Sup{
        constructor(...args){
            console.log('Serialization constructor~~~');
            super(...args)
            if (typeof(this.stringfy)!== "function") {
                throw new ReferenceError('should defined stringfy');
            }
        }
    }
    class Point {
        constructor(x, y) {
            console.log("point constructor");
            this.x = x
            this.y = y
        }
     
    }
     
    class Point3D extends Serialization(Point) /*返回一个新类*/{
        constructor(x,y,z){
            super(x,y);
            this.z = z
        }
        stringfy (){
            return `<Point3d ${this.x}.${this.y}.>`
        }
    }
     
    cls = new Point3D(4,5,6)
    console.log(cls)
     
    这个cls 实际上可以使用三个类的方法,因为这个类的定义中实际混合两个类的 混合返回的新类
  • 相关阅读:
    Quartz.Net系列(二):介绍、简单使用、对比Windows计划任务
    Quartz.Net系列(一):Windows任务计划程序
    Linux下swap到底有没有必要使用
    Linux服务器有大量的TIME_WAIT状态
    HTTP请求头中的X-Forwarded-For介绍
    Keepalived实现服务高可用
    Gitlab常规操作
    Git 常用命令
    HTTP常见状态码
    《Docker从入门到跑路》之多阶段构建
  • 原文地址:https://www.cnblogs.com/spidermansam/p/8286639.html
Copyright © 2020-2023  润新知