Proxy
time 0m
不常用的Proxy操作
回顾原型内容
time 9m10s
function Person(name = 'zhangsan', age = '18') {this.name = name;this.age=age;}Person.prototype.say=function () {console.log(`my name is ${this.name},my age is ${this.age}`);}new Person('lisi','19').say();console.log(new Person());

time 18m39s
function Person(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}Person.prototype.say = function () {console.log(`my name is ${this.name},my age is ${this.age}`);}var person= new Person('lisi', '19');// console.log(new Person());console.log(Object.getPrototypeOf(person));console.log(Object.getPrototypeOf(person).constructor===Person);//trueconsole.log(Person.prototype===Object.getPrototypeOf(person));//true

class
time 19m28s
es6新的关键字class,es5以前是保留字,也不可以var class,变量不能以关键字命名
class(类),js中严格来说是不存在class类的,主要在类c语言,c++、java纯面向对象的编程语言当中,是在模拟一个类的方式
本质上是一个语法糖,本质上还是函数,只不过通过class关键字把它重新封装了一遍,本身什么都没有改变,就是写法上面改变了,可以让可读性、维护性、减少出错机会,这是class的作用
用class类的方式模拟function构造函数
time 22m06s
//class(类)class Person {}console.log(new Person())console.log(typeof Person);//function

私有属性、公有属性、静态属性
time 25m50s
//class(类)class Person {constructor(name = 'zhangsan', age = '18') {/*实例化的属性配置:私有属性;因为每一个对象都不一样,实例化对象时传的参数可能不同,* 每个对象的这些值的value具体值可能不一样,不能共享,新建了两个人,一个老师、一个学生,* 他们不可能共享名字与年龄*/this.name = name;this.age = age;}/*公有属性*/say(){console.log(`my name is ${this.name}, my age is ${this.age}`);}}console.log(new Person())console.log(typeof Person);//function

assign
time 37m31s
function Person(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}Person.prototype.say = function () {console.log(`my name is ${this.name},my age is ${this.age}`);}Object.assign(Person.prototype, {eat:function() {console.log(`I can eat`);},drink(){console.log(`I can drink`);}})/*可枚举,这种方式出来的属性是可以枚举的*/
class不能枚举
time 38m09s
//class(类)class Person {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}/*公有属性*/say() {console.log(`my name is ${this.name}, my age is ${this.age}`);}/*这样定义时错的,用简写定义*//* eat:function() {//Uncaught SyntaxError: Unexpected identifierconsole.log(`I can eat`);}*/eat() {console.log(`I can eat`);}drink() {console.log(`I can drink`);}}console.log(new Person());//类内部的方法是不可枚举的console.log(Object.keys(Person.prototype));
默认添加constructor,如果没有自定义
time 40m
class Person {}/*没写等效于下面代码,自动给添加,new就必须有constructor才能new,* 必须有constructor才能new*//* class Person {constructor() {}}*/console.log(new Person());

constructor与return
time 43m24s
class Person {constructor() {return Object.create(null);}}console.log(new Person() instanceof Person);//false
time 44m
function Person() {}console.log(new Person() instanceof Person);//true
class Person {}console.log(new Person() instanceof Person);//true
函数表达式
time 46m39s
var test=function (){}/*可以加个函数名,但这个函数名没有任何意义,一般可以省略* 上面的写法是一般写法*/var test=function test1(){}
time 48m08s
/*class Person{say(){console.log(1)}}*/var Foo=class Person{say(){console.log(1)}}var Person=class{say(){console.log(1)}}new Person().say();//1
class必须通过new的方式执行
time 49m
不像function可以当函数直接运行,也可以当构造函数
/*必须通过new 的方式执行 class(表达式的方式)*/var Person = class {say() {console.log(1)}}()Person.say();//TypeError: Class constructors cannot be invoked without 'new'
/*必须通过new 的方式执行 class*/var person = new class {say() {console.log(1)}}();person.say();//1
time 50m46s
知道这种写法就行了,别这样用
/*必须通过new 的方式执行 class*/var person = new class {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}say() {console.log(1)}}('lisi', '19');person.say();//1console.log(person);//{ name: 'lisi', age: '19' }
class不能提升
time 54m
console.log(new Person());//Person {}function Person() {}
time 54m03s
console.log(new Person());//ReferenceError: Cannot access 'Person' before initialization//不存在TDZclass Person {}
属性自定义
time 55m38s
通过class定义,公有的方法可以,但公有的属性不可以,在原型上定义的是公有的,属性定义不到原型上面
class Person {/*es2017新写法,等于在constructor里面写* a不是在原型上面定义*/a = 1;constructor() {// this.a=1;}/* Person.prototype.say={}*//* this.person.say={}*//*say等于在原型上面定义*/say() {}}console.log(new Person());//Person { a: 1 }

私有方法
time 1h1m04s
上面的定义,方法都是共有的,但我想让它们私有,不想暴露给外面有什么办法
symbol方式
time 1h3m
const eat=Symbol();class Person {/*es2017新写法,等于在constructor里面写* a不是在原型上面定义*/a = 1;constructor() {// this.a=1;}/* Person.prototype.say={}*//* this.person.say={}*//*say等于在原型上面定义*/say() {console.log(1);}[eat](){console.log(2);}}console.log(new Person().say());//1console.log(new Person().eat());/*new Person()['eat'](),因为eat变量是Symbol定义的是独一无二的值,而不是‘eat’字符串,所以访问不到*//*undefined*Uncaught TypeError: (intermediate value).eat is not a function */
写外面配合call
time 1h5m
const eat=Symbol();class Person {// a = 1;constructor(name,age) {this.name = name;this.age = age;}say(baz) {console.log(this,baz);}}function children(baz){return this.bar=baz;}console.log(new Person().say());
static
time 1h7m50s
class Person {static a=1;}console.log(new Person());console.log(new Person().a);//undefinedconsole.log( Person.a);//1
time 1h10m37s
class Person {static a=1;}console.log(new Person());console.log(new Person().a);//undefinedconsole.log( Person.a);//1

class Person {static a(){console.log(1);}}console.log(new Person());console.log(new Person().a);//undefinedconsole.log( Person.a);//1

给函数本身赋值属性,一般不会这样做
相当于以下代码,用static关键字实现了以下代码
time 13m50s
相当于在外界进行Person.a=10;操作,更方便
静态方法是没有问题的,属性 得升级Chrome版本;
class Person {// static a=10;}Person.a=10;
get
time 1h15m41s
time 1h17m16s
class Person {get a() {console.log(1)}set b(value) {console.log(2)}}var person=new Person();person.a;//1person.b=4;//2
time 1h20m36s
默认是严格模式的
“use strict”;
不难,多练几遍就会了,以后都会用这种写法
总结
time 1h21m58s
继承
time 1h28m02s
extends
time 1h30m22s
class Parent {constructor(name = 'zhangsan') {this.name = name;}}class Child extends Parent {}console.log(new Child());//Child { name: 'zhangsan' }
class Parent {constructor(name = 'zhangsan') {this.name = name;}say(){console.log(1);}static a(){console.log(2)}}/*派生类*/class Child extends Parent {}// console.log(new Child());/*能继承原型上面的属性*/console.log(new Child().say());//1/*能继承构造器上面的属性*/console.log(new Child().name);//zhangsan/*不能继承static上面的属性*/console.log(new Child().a())//Uncaught TypeError: (intermediate value).a is not a function
class实现传值
time 1h33m37s
class Parent {constructor(name = 'zhangsan') {this.name = name;}say(){console.log(1);}}//派生类class Child extends Parent{constructor(name = 'zhangsan') {/*必须加super*/// super();this.name = name;}say(){console.log(1);}}console.log(new Child())/*Uncaught ReferenceError: Must call super constructor in derived class before accessing'this' or returning from derived constructo*/
class Parent {constructor(name = 'zhangsan') {this.name = name;}say(){console.log(1);}}//派生类class Child extends Parent{constructor(age = '19') {/*必须加super*//*因为new Child()没有传值*/// super(name);//Child{name: '', type: 'child', age: '19'}// super();//Child{name: 'zhangsan', type: 'child', age: '19'}/*相当于先运行Parent父级的构造函数,new Parent(age=19)*/super(age);//Child{name: '19', type: 'child', age: '19'}this.type='child';this.age = age;}say(){console.log(1);}}console.log(new Child())
time 1h41m38s
super第一种用法,继承父类的属性
在constructor里的,以函数的方式来执行
class Parent {constructor(name = 'zhangsan') {this.name = name;}say(){console.log(1);}}//派生类class Child extends Parent{constructor(age = '19',name = 'lisi') {super(name);//Child{name: '19', type: 'child', age: '19'}this.type='child';this.age = age;}say(){console.log(1);}}console.log(new Child())//Child{name: 'lisi', type: 'child', age: '19'}
第二种用法
time 1h44m55s
let proto = {y: 20,z: 40}let obj={x:10,foo(){console.log(super.y)//20console.log(this.y)//20}}Object.setPrototypeOf(obj,proto);console.log(obj);obj.foo()

time 1h48m
class特征
time 1h53m30s
package.json
time 1h55m
'use strict';var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}var Parent = function () {function Parent() {var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'zhangsan';var age = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '18';_classCallCheck(this, Parent);this.name = name;this.age = age;}_createClass(Parent, [{key: 'say',value: function say() {console.log('hello world');}}, {key: 'drink',value: function drink() {console.log('drink');}}], [{key: 'eat',value: function eat() {console.log('eat');}}]);return Parent;}();/*class Child extends Parent {}console.log(new Child());//Child { name: 'zhangsan' }*/
core-decorators
npm install core-decorators —save
安装,官网最新版本 0.20.0
源码分析
time 1h59m
'use strict';var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}var Parent = function () {function Parent() {var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'zhangsan';var age = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '18';_classCallCheck(this, Parent);this.name = name;this.age = age;}_createClass(Parent, [{key: 'say',value: function say() {console.log('hello world');}}, {key: 'drink',value: function drink() {console.log('drink');}}], [{key: 'eat',value: function eat() {console.log('eat');}}]);return Parent;}();/*class Child extends Parent {}console.log(new Child());//Child { name: 'zhangsan' }*/
time 2h28m08s
1听课听明白
2理解代码、源码 ,把顺序理下来
3复写一遍,先照真写,之后看看能不能托手写
考验大家的是一种逻辑能力
并不难,按照一定的顺序
修饰器
time 2h29m33s
修饰器模式
time 2h32m53s
代理是完全拦截,不允许访问(被代理的对象)
修饰器可以访问对象,仅仅是帮助修饰一下,仅仅是修饰作用,给你添加一些新的功能
/*修饰器模式:为对象添加新的功能,而不改变原有的结构和功能*/class Parent {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}@readonlysay() {console.log('hello world');}static eat() {console.log('eat')}static eat1() {console.log('eat')}}
time 2h38m50s
npm i babel-plugin-transform-decorators-legacy —save-dev
time 2h44m
{"presets": ["babel-preset-env"],"plugins": ["transform-decorators-legacy"]}
本身不支持
time 2h47m33s
/*修饰器模式:为对象添加新的功能,而不改变原有的结构和功能*/@testable/*SyntaxError: Invalid or unexpected token* 不支持这个语法,报错*/class Parent {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}say() {console.log('hello world');}static eat() {console.log('eat')}static eat1() {console.log('eat')}}let person=new Person();console.log(person);function testable(target) {console.log(target)}
run build
time 2h49m47s
'use strict';var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _class;function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}/*SyntaxError: Invalid or unexpected token* 不支持这个语法,报错*/var Parent = testable(_class = function () {function Parent() {var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'zhangsan';var age = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '18';_classCallCheck(this, Parent);this.name = name;this.age = age;}_createClass(Parent, [{key: 'say',value: function say() {console.log('hello world');}}], [{key: 'eat',value: function eat() {console.log('eat');}}, {key: 'eat1',value: function eat1() {console.log('eat');}}]);return Parent;}()) || _class;var person = new Person();console.log(person);function testable(target) {console.log(target);}
time 2h50m05s
把bundle在html引入,运行
target就是要修饰的对象本身
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title></title></head><body><script src="./bundle.js"></script><script !src=""></script></body></html>

time 2h55m06s
class Parent {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}@readonlysay() {console.log('hello world');}eat(){console.log('eat')}}function readonly(target,name,descriptor) {console.log(target,name,descriptor)}


time 3h3m45s
class Person {constructor(name = 'zhangsan', age = '18') {this.name = name;this.age = age;}@readonlysay() {console.log('hello world');}eat(){console.log('eat')}}function readonly(target,name,descriptor) {// console.log(target,name,descriptor)console.log(descriptor);descriptor.writable = false;}let person=new Person();person.say=function() {console.log(1)}

修改eat可以修改,只不过say不能修改
这样可以让业务和逻辑分离
应用:埋点
time 3h15m40s
let log = type => {return function (target, name, descriptor) {let src_method = descriptor.value;descriptor.value = (...arg) => {src_method.apply(target, arg);console.log(type);}}}class AD {@log('show')show() {console.log('ad is show');}@log('click')click() {console.log('ad is click')}}let ad = new AD();ad.show();ad.click();

这种方式不怎么用

