ES-6学习笔记之class类

/*

* es6中模块和类整个属于严格模式

*

*

* 总结:

*  1.私有属性,

*  2.私有方法, --> es6并未提供,添加私有属性或私有方法的三种方式

*      1.通过符号标识

*      2.通过把类中引用的私有方法拉出

*      3.通过Symbol的唯一性进行处理

*  3.静态属性,通过Class.call = 'zhangsan'设置

*  4.静态方法,static call () {} 为类的方法

*  5.set和get关键字,

*      与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为

*  es类定义的方法皆为不可枚举

*  6.新建对象时,必须加new(可使用new.target进行判断是否加了new,不加new,此时的new.target为undefined,加了后则指向构造函数)

*  7.不进行变量提升 --> 考虑到父类可能用let进行表达式方式定义

*  8.this的指向

*      类的this指向一般为新建的实例,但当类中的函数通过别的方式被复制后结果未必,如

*      {

class Parent {

constructor (name, age) {

this.name = name;

this.age = age;

}

tell () {//函数在执行的时候再去找调用其的对象,把this指向它

console.log(`我叫${this.name}, 今年${this.age}岁了`);

}

}

let parent = new Parent('zhangsan', 20);

let tell = parent.tell;

//tell();//此时报错

}

{

class Parent {

constructor (name, age) {

this.name = name;

this.age = age;

// this.tellSelf = this.tell.bind(this);//提前把this指向给Parent

this.tellSelf = () => {this.tell()};//此时的this也已经被指向了Parent

}

tell () {

console.dir(this);

console.log(`我叫${this.name}, 今年${this.age}岁了`);

}

}

let parent = new Parent('zhangsan', 20);

let tell = parent.tellSelf;

console.dir(tell);

tell();//正常

}

{

console.log('==============')

//Proxy:在目标对象前架设一层拦截,通过其对对象进行增删改查,并自定义设置增删改查的行为

class Parent {

constructor (name, age) {

this.name = name;

this.age = age;

}

tell () {

console.log(`我叫${this.name}, 今年${this.age}岁了`);

}

}

//封装一个返回Proxy实例的函数

function getProxy (target) {

const cache = new WeakMap();//此处实现了闭包,所以此cache就有了实际的意义

let handler = {

get (target, key) {

const value = Reflect.get(target, key);

if (typeof value !== "function") {

return value;

}

if (!cache.has(value)) {

//cache.set(value, value);

cache.set(value, value.bind(target));//此处把所有方法的this都指向了target

}

return cache.get(value);

}

};

return new Proxy(target, handler);

}

let parentProxy = getProxy(new Parent('zhangsan', 30));

let tell = parentProxy.tell;

tell();

}

*

*

*

*

*  9.遍历器属性的添加(Symbol.iterator或者Generator函数)

*      想使生成的实例能够使用for...of方法或...real,在prototype上设置 Symbol.iterator属性 或 Generator函数

*      {

class Parent {

constructor (...arg) {

this.arg = arg;

}

*[Symbol.iterator] () {//Generator函数通过为prototype添加Symbol.iterator属性

for (let i of this.arg) {

yield '哈哈' + i;

}

}

}

let parent = new Parent(1, 2, 3, 4);

for (let i of parent) {

console.log(i);

}

}

*

*

*

*  10.类的继承:

*      > 在构造函数中必须执行super函数,因为ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。

*      > es5和es6实现this的方式不同,导致对于原生构造函数属性的继承和扩展出现根本的不同,如下代码:原因是原生构造函数内部属性不能被子类的this拿去

*          {

class MyArray extends Array {

constructor (...arg) {//此处...arg为把传入的实参转化为数组arg

super(...arg);//此处...arg则是把数组拆开

}

}

let array = new MyArray(1, 2, 3, 4);

console.dir(array);//此时等同于对Array的复制

}

{

function MyArray (...arg) {

Array.apply(this, arg)

}

//实现了父级的prototype的实例为子级函数的protype

MyArray.prototype = Object.create(Array.prototype, {

constructor: {

value: MyArray,//显示的值

configurable: true,//

enumerable: true,//可枚举性

writable: true //可修改

}

});//Object.create(A, B);把A复制给B的__proto__,返回

let array = new MyArray(1, 2, 3, 4);

console.dir(array);//此处1,2,3,4不能显示

array[0] = 1;

console.log(array[0]);//1

console.log(array.length);//0

}

*

*

*

*      > super的指向问题

*          1)在构造函数中可以做为函数执行

*          2)作为对象执行时必须带有属性,此时指向this(狭隘的理解为等同于this)

*          3)只有这两种用法,其他方式报错

*      > prototype和__proto__指向

*          1)子类的prototype指向父类原型的实例,和es5一致

*          2)子类的__proto__指向为父类构造函数而es5中子类的__proto__指向为unction的实例

*      > 可以通过Reflect.getPrototypeOf(A)或Object.getPrototypeOf(A)获取A的父类

*          function getPrototypeOf(A) {

*              let B = A.__proto__;

*              return B;

*          }

*

*

*  11. new.target指向的是正在执行的构造函数

*      在子类执行函数时,父类构造函数中的new.target指向的为子类的构造函数,且this为new.target的实例

*

*  12.mixins混合

*      {

//Mixin模式实现

function mixin(...mixins) {

class Mix {}

for (let mixin of mixins) {

copyProperties(Mix, mixin);

copyProperties(Mix.prototype, mixin.prototype);

}

return Mix;

}

function copyProperties (target, source) {

for (let key of Reflect.ownKeys(source)) {

//属性的复制,不仅仅是value的复制,还有enumerable,configurable,writable

if (key !== 'constructor' && key !== 'name' && key !== 'prototype') {

let desc = Reflect.getOwnPropertyDescriptor(source, key);

Reflect.defineProperty(target, key, desc);

}

}

}

}

*

* 原生构造函数:

*  Array,String,Object,RegExp,Date,Error,Function,Number,Boolean,Event等

*

*

*

* 对象的理解:属性的四个属性值:value,enumerable,writable,configurable等

* Object的一些方法:Object.create(),及一些和Reflect一样的方法,如:

*  defineProperty(),deleteProperty(),getOwnPropertyDescriptor(),has(),ownKeys(),get(),set()等

*

* arguments.callee.caller.arguments[0] == event 的理解

*

* arguments的属性:

*  callee --> 指代当前函数

*  length

*当前函数的属性:

*  caller --> 指代调用当前函数的函数(严格模式下不可使用)

*

*  火狐浏览器下:arguments.callee.caller为用户绑定的事件监听函数的事件函数,参数有event

*

*  严格模式下,arguments和caller,callee有可能不可使用

* */

参考自阮一峰es6入门  http://es6.ruanyifeng.com/#docs/class#Class-的-Generator-方法

你可能感兴趣的:(ES-6学习笔记之class类)