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);//true
console.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 identifier
console.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();//1
console.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
//不存在TDZ
class 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());//1
console.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);//undefined
console.log( Person.a);//1
time 1h10m37s
class Person {
static a=1;
}
console.log(new Person());
console.log(new Person().a);//undefined
console.log( Person.a);//1
class Person {
static a(){
console.log(1);
}
}
console.log(new Person());
console.log(new Person().a);//undefined
console.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;//1
person.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)//20
console.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;
}
@readonly
say() {
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;
}
@readonly
say() {
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;
}
@readonly
say() {
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();
这种方式不怎么用