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 实际上可以使用三个类的方法,因为这个类的定义中实际混合两个类的 混合返回的新类

posted on 2018-01-15 09:08  pythonerLau  阅读(233)  评论(0编辑  收藏  举报

导航