interface IStorage {
save(key: any, value: any): void;
read(key: any): void;
}
class LocalStorage implements IStorage {
save(key: any, value: any) {
localStorage.setItem(key, value);
}
read(key: any) {
return localStorage.getItem(key);
}
}
class User {
constructor(public name: string, public storage: IStorage) {
}
save() {
this.storage.save('userInfo', JSON.stringify(this));
}
read() {
return this.storage.read('userInfo');
}
}
let user = new User('张三', new LocalStorage());
user.save();
user.read();
is-a
关系export { };
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log(`${this.name} eat`)
}
}
let animal = new Animal('动物');
animal.eat();
class Dog extends Animal {
age: number;
constructor(name: string, age: number) {
super(name);
this.age = age;
}
speak() {
console.log(`${this.name} is barking!`);
}
}
let dog = new Dog('🐶', 5);
dog.eat();
dog.speak();
过度使用继承或者说继承层次过深会导致代码可读性、可维护性变差 子类和父类高度耦合,修改父类的代码,会直接影响到子类
class Animal {
public name: string;
protected age: number;
private weight: number;
constructor(name: string, age: number, weight: number) {
this.name = name;
this.age = age;
this.weight = weight;
}
}
class Person extends Animal {
private money: number;
constructor(name: string, age: number, weight: number, money: number) {
super(name, age, weight);
this.money = money;
}
getName() {
console.log(this.name);
}
getAge() {
console.log(this.age);
}
getWeight() {
console.log(this.weight);
}
getMoney() {
console.log(this.money);
}
}
let p = new Person('zfpx', 9, 100, 100);
console.log(p.name);
console.log(p.age);
console.log(p.weight);
class Animal {
public name: string;
protected age: number;
private weight: number;
constructor(name: string, age: number, weight: number) {
this.name = name;
this.age = age;
this.weight = weight;
}
speak() {
throw new Error('此方法必须由子类实现!');
}
}
class Person extends Animal {
private money: number;
constructor(name: string, age: number, weight: number, money: number) {
super(name, age, weight);
this.money = money;
}
getName() {
console.log(this.name);
}
getAge() {
console.log(this.age);
}
getMoney() {
console.log(this.money);
}
speak() {
console.log('你好!');
}
}
class Dog extends Animal {
constructor(name: string, age: number, weight: number) {
super(name, age, weight);
}
speak() {
console.log('汪汪汪!');
}
}
let p = new Person('zfpx', 10, 10, 10);
p.speak();
let d = new Dog('zfpx', 10, 10);
d.speak();
首字母 | 指代 | 概念 |
---|---|---|
S | 单一职责原则 | 单一功能原则认为对象应该仅具有一种单一功能 的概念 |
O | 开放封闭原则 | 开闭原则认为软件体应该是对于扩展开放的,但是对于修改封闭的 的概念 |
L | 里氏替换原则 | 里氏替换原则认为程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换 的的概念 |
I | 接口隔离原则 | 接口隔离原则认为多个特定客户端接口要好于一个宽泛用途的接口 的概念 |
D | 依赖反转原则 | 依赖反转原则认为一个方法应该遵从依赖于抽象而不是一个实例 的概念,依赖注入是该原则的一种实现方式。 |
Open Closed Principle
class Customer {
constructor(public rank: string) { }
}
class Product {
constructor(public name: string, public price: number) {
}
cost(customer: Customer) {
switch (customer.rank) {
case 'member':
return this.price * .8;
case 'vip':
return this.price * .6;
default:
return this.price;
}
}
}
let p1 = new Product('笔记本电脑', 1000);
let member = new Customer('member');
let vip = new Customer('vip');
let guest = new Customer('guest');
console.log(p1.cost(member));
console.log(p1.cost(vip));
console.log(p1.cost(guest));
class Customer {
+ constructor(public rank: string, public discount: number = 1) { }
+ getDiscount() {
+ return this.discount;
+ }
}
class Product {
constructor(public name: string, public price: number) {
}
cost(customer: Customer) {
- /* switch (customer.rank) {
- case 'member':
- return this.price * .8;
- case 'vip':
- return this.price * .6;
- default:
- return this.price;
- } */
+ return this.price * customer.getDiscount();
}
}
+let p1 = new Product('笔记本电脑', 1000);
+let member = new Customer('member', .8);
+let vip = new Customer('vip', .6);
let guest = new Customer('guest');
console.log(p1.cost(member));
console.log(p1.cost(vip));
console.log(p1.cost(guest));
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
let instance: AxiosInstance = axios.create();
instance.interceptors.request.use((config: AxiosRequestConfig) => {
config.url = 'http://localhost:8080' + config.url;
return config;
});
instance.interceptors.response.use(response => {
if (response.status !== 200 || response.data.code != 0) {
return Promise.reject(response);
} else {
return response.data.data;
}
})
/**
* {code:0,data:{id:1,name:'zhufeng'}}
*/
instance({
url: '/api/users'
}).then(result => {
console.log(result);
}, error => {
console.error(error);
});
拆分不能过度,如果拆分过度会损失内聚性和维护性
class Product {
public name: string;
- public categoryName: string;
- public categoryIcon: string;
+ public category:Category;
}
+class Category {
+ public name: string;
+ public icon: string;
+}
abstract class AbstractDrink {
abstract getName(): string;
}
class CocaCola extends AbstractDrink {
getName(): string {
return '可乐';
}
}
class Sprite extends AbstractDrink {
getName(): string {
return '雪碧';
}
}
class Fanta extends AbstractDrink {
getName(): string {
return '芬达';
}
}
class Customer {
drink(drink: AbstractDrink) {
console.log('喝' + drink.getName());
}
}
let customer = new Customer();
let cocaCola = new CocaCola();
let sprite = new Sprite();
let fanta = new Fanta();
customer.drink(cocaCola);
customer.drink(sprite);
customer.drink(fanta);
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return (
<div>App </div>
)
}
}
let element = React.createElement(App);
ReactDOM.render(element, document.getElementById('root'));
abstract class AbstractDrink {
abstract getName(): any;
}
class CocaCola extends AbstractDrink {
getName(): any {
return 100;
}
}
abstract class GirlFriend {
public age: number;
public height: number;
public abstract cook(): void;
}
class LinZhiLing extends GirlFriend {
public cook(): void {
}
}
class HanMeiMei extends GirlFriend {
public cook(): void {
}
}
class SingleDog {
constructor(public girlFriend: GirlFriend) {
}
}
let s1 = new SingleDog(new LinZhiLing());
let s2 = new SingleDog(new HanMeiMei());
import { createStore } from 'redux';
let store = createStore(state => state);
export interface Action<T = any> {
type: T
}
export interface AnyAction extends Action {
// Allows any extra properties to be defined in an action.
[extraProps: string]: any
}
let action: AnyAction = { type: 'increment', payload: 5 }
store.dispatch(action);
interface IUserManager {
updateUserInfo(): void;
updatePassword(): void;
}
interface IProductManager {
updateProduct(): void;
updatePrice(): void;
}
interface Running {
run(): void;
}
interface Flying {
fly(): void;
}
interface Swimming {
swim(): void;
}
class Automobile implements Running, Flying, Swimming {
run() { }
fly() { }
swim() { }
}
public
修饰符,尽量使用private
、protected
等class Salesman {
constructor(public name: string) {
}
sale() {
console.log(this.name + ' 销售中....');
}
}
class SaleManager {
private salesmen: Array<Salesman> = [new Salesman('张三'), new Salesman('李四')];
sale() {
this.salesmen.forEach(salesman => salesman.sale());
}
}
class CEO {
private saleManager: SaleManager = new SaleManager();
sale() {
this.saleManager.sale();
}
}
let ceo = new CEO();
ceo.sale();
拥有
关系,代表部分的对象可能会被整体拥有,但并不定定会随着整体的消亡而销毁,比如班级和学生class Cooker {
cook() {
}
}
class Person {
private cooker: Cooker = new Cooker();
cook() {
this.cooker.cook();
}
}
重要: 工厂模式(工厂方法模式、抽象工厂模式、简单工厂模式)、建造者模式、单例模式
重要: 代理模式、桥接模式、装饰器模式、适配器模式
重要: 观察者模式、模版方法模式、策略模式、职责链模式、迭代器模式、状态模式
abstract class Coffee {
constructor(public name: string) {
}
}
class AmericanoCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class LatteCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class CappuccinoCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class Café {
static order(name: string) {
switch (name) {
case 'Americano':
return new AmericanoCoffee('美式咖啡');
case 'Latte':
return new LatteCoffee('拿铁咖啡');
case 'Cappuccino':
return new LatteCoffee('卡布奇诺');
default:
return null;
}
}
}
console.log(Café.order('Americano'));
console.log(Café.order('Latte'));
console.log(Café.order('Cappuccino'));
switch case
的判断会变得非常多switch case
的判断代码class jQuery{
constructor(selector){
let elements = Array.from(document.querySelectorAll(selector));
let length = elements?elements.length:0;
for(let i=0;i<length;i++){
this[i]=elements[i];
}
this.length = length;
}
html(html){
if(html){
this[0].innerHTML=html;
}else{
return this[0].innerHTML;
}
}
}
window.$ = function(selector){
return new jQuery(selector);
}
export function createElement(type, config, children) {
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
Factory Method
,又称多态性工厂模式。export { }
abstract class Coffee {
constructor(public name: string) {
}
}
abstract class Factory {
abstract createCoffee(): Coffee;
}
class AmericanoCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class AmericanoCoffeeFactory extends Factory {
createCoffee() {
return new AmericanoCoffee('美式咖啡')
}
}
class LatteCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class LatteCoffeeFactory extends Factory {
createCoffee() {
return new LatteCoffee('拿铁咖啡')
}
}
class CappuccinoCoffee extends Coffee {
constructor(public name: string) {
super(name);
}
}
class CappuccinoFactory extends Factory {
createCoffee() {
return new CappuccinoCoffee('卡布奇诺')
}
}
class Café {
static order(name: string) {
switch (name) {
case 'Americano':
return new AmericanoCoffeeFactory().createCoffee();
case 'Latte':
return new LatteCoffeeFactory().createCoffee();
case 'Cappuccino':
return new CappuccinoFactory().createCoffee();
default:
return null;
}
}
}
console.log(Café.order('Americano'));
console.log(Café.order('Latte'));
console.log(Café.order('Cappuccino'));
export { };
abstract class AmericanoCoffee { }
abstract class LatteCoffee { }
abstract class CappuccinoCoffee { }
class StarbucksAmericanoCoffee extends AmericanoCoffee { }
class StarbucksLatteCoffee extends LatteCoffee { }
class StarbucksCappuccinoCoffee extends CappuccinoCoffee { }
class LuckinAmericanoCoffee extends AmericanoCoffee { }
class LuckinLatteCoffee extends LatteCoffee { }
class LuckinCappuccinoCoffee extends CappuccinoCoffee { }
abstract class CafeFactory {
abstract createAmericanoCoffee(): AmericanoCoffee;
abstract createLatteCoffee(): LatteCoffee;
abstract createCappuccinoCoffee(): CappuccinoCoffee;
}
class StarbucksCafeFactory extends CafeFactory {
createAmericanoCoffee() {
return new StarbucksAmericanoCoffee();
}
createLatteCoffee() {
return new StarbucksLatteCoffee();
}
createCappuccinoCoffee() {
return new StarbucksCappuccinoCoffee();
}
}
class LuckinCafeFactory extends CafeFactory {
createAmericanoCoffee() {
return new LuckinAmericanoCoffee();
}
createLatteCoffee() {
return new LuckinLatteCoffee();
}
createCappuccinoCoffee() {
return new LuckinCappuccinoCoffee();
}
}
let starbucksCafeFactory = new StarbucksCafeFactory();
console.log(starbucksCafeFactory.createAmericanoCoffee());
console.log(starbucksCafeFactory.createCappuccinoCoffee());
console.log(starbucksCafeFactory.createLatteCoffee());
let luckinCafeFactory = new LuckinCafeFactory();
console.log(luckinCafeFactory.createAmericanoCoffee());
console.log(luckinCafeFactory.createCappuccinoCoffee());
console.log(luckinCafeFactory.createLatteCoffee());
export { };
class Window {
private static instance: Window;
private constructor() { }
static getInstance() {
if (!Window.instance) {
Window.instance = new Window();
}
return Window.instance;
}
}
//new Window();
var w1 = Window.getInstance();
var w2 = Window.getInstance();
console.log(w1 === w2);
interface Window {
hello: any
}
function Window() { }
Window.prototype.hello = function () {
console.log('hello');
}
Window.getInstance = (function () {
let window: Window;
return function () {
if (!window)
window = new (Window as any)();
return window;
}
})();
let window = Window.getInstance();
window.hello();
let Window = (function () {
let window: Window;
let Window = function (this: Window) {
if (window) {
return window;
} else {
return (window = this);
}
}
Window.prototype.hello = function () {
console.log('hello');
}
return Window;
})();
let window1 = new (Window as any)();
let window2 = new (Window as any)();
window1.hello();
console.log(window1 === window2)
export { }
interface Window {
hello: any
}
function Window() {
}
Window.prototype.hello = function () {
console.log('hello');
}
let createInstance = (function () {
let instance: Window;
return function () {
if (!instance) {
instance = new (Window as any)();
}
return instance;
}
})();
let window1 = createInstance();
let window2 = createInstance();
window1.hello();
console.log(window1 === window2)
export { }
function Window() {
}
Window.prototype.hello = function () {
console.log('hello');
}
let createInstance = function (Constructor: any) {
let instance: any;
return function (this: any) {
if (!instance) {
Constructor.apply(this, arguments);
Object.setPrototypeOf(this, Constructor.prototype)
instance = this;
}
return instance;
}
};
let CreateWindow: any = createInstance(Window);
let window1 = new CreateWindow();
let window2 = new CreateWindow();
window1.hello();
console.log(window1 === window2)
(function(modules) {
// webpack的启动函数
//模块的缓存
var installedModules = {};
//定义在浏览器中使用的require方法
function __webpack_require__(moduleId) {
//检查模块是否在缓存中
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
//创建一个新的模块并且放到模块的缓存中
var module = (installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
});
//执行模块函数
modules[moduleId].call(
module.exports,
module,
module.exports,
__webpack_require__
);
//把模块设置为已经加载
module.l = true;
//返回模块的导出对象
return module.exports;
}
}
if(window.jQuery!=null){
return window.jQuery;
}else{
//init~~~~~~~
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="show-button">显示模态窗口</button>
<button id="hide-button">隐藏模态窗口</button>
<script>
class Login {
constructor() {
this.element = document.createElement('div');
this.element.innerHTML = (
`
用户名 <input type="text"/>
<button>登录</button>
`
);
this.element.style.cssText = 'width: 100px; height: 100px; position: absolute; left: 50%; top: 50%; display: block;';
document.body.appendChild(this.element);
}
show() {
this.element.style.display = 'block';
}
hide() {
this.element.style.display = 'none';
}
}
Login.getInstance = (function () {
let instance;
return function () {
if (!instance) {
instance = new Login();
}
return instance;
}
})();
document.getElementById('show-button').addEventListener('click', function (event) {
Login.getInstance().show();
});
document.getElementById('hide-button').addEventListener('click', function (event) {
Login.getInstance().hide();
});
</script>
</body>
</html>
function createStore(reducer: any) {
let state: any;
let listeners: any[] = [];
function getState() {
return state;
}
function dispatch(action: any) {
state = reducer(state, action);
listeners.forEach(l => l());
}
function subscribe(listener: any) {
listeners.push(listener);
return () => {
listeners = listeners.filter(item => item != listener);
console.log(listeners);
}
}
dispatch({});
return {
getState,
dispatch,
subscribe
}
}
let store = createStore((state: any, action: any) => state);
let express = require('express');
let fs = require('fs');
let cache: Record<any, any> = {};
let app = express();
app.get('/user/:id', function (req: any, res: any) {
let id = req.params.id;
let user = cache.get(id);
if (user) {
res.json(user);
} else {
fs.readFile(`./users/${id}.json`, 'utf8', function (err: any, data: any) {
let user = JSON.parse(data);
cache.put(id, user);
res.json(user);
});
}
});
app.listen(3000);
class Socket {
output() {
return '输出220V';
}
}
abstract class Power {
abstract charge(): string;
}
class PowerAdapter extends Power {
constructor(public socket: Socket) {
super();
}
//转换后的接口和转换前不一样
charge() {
return this.socket.output() + ' 经过转换 输出24V';
}
}
let powerAdapter = new PowerAdapter(new Socket());
console.log(powerAdapter.charge());
config
,返回的都是promise
//let axios = require('axios');
let url = require('url');
function axios(config: any): any {
let adaptor = getDefaultAdapter();
return adaptor(config);
}
axios({
method: 'GET',
url: 'http://localhost:8080/api/user?id=1'
}).then(function (response: any) {
console.log(response);
}, function (error: any) {
console.log(error);
})
function xhr(config: any) {
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open(config.method, config.url, true);
request.onreadystatechange = function () {
if (request.readyState == 4) {
if (request.status == 200) {
resolve(request.response);
} else {
reject('请求失败');
}
}
}
})
}
function http(config: any) {
let http = require('http');
let urlObject = url.parse(config.url);
return new Promise(function (resolve, reject) {
const options = {
hostname: urlObject.hostname,
port: urlObject.port,
path: urlObject.pathname,
method: config.method
};
var req = http.request(options, function (res: any) {
let chunks: any[] = [];
res.on('data', (chunk: any) => {
chunks.push(chunk);
});
res.on('end', () => {
resolve(Buffer.concat(chunks).toString());
});
});
req.on('error', (err: any) => {
reject(err);
});
req.end();
})
}
function getDefaultAdapter(): any {
var adapter;
if (typeof XMLHttpRequest !== 'undefined') {
adapter = xhr;
} else if (typeof process !== 'undefined') {
adapter = http;
}
return adapter;
}
server.js
let express = require('express');
let app = express();
app.get('/api/user', (req, res) => {
res.json({ id: req.query.id, name: 'zhufeng' });
});
app.listen(8080);
function toAxiosAdapter(options: any) {
return axios({
url: options.url,
method: options.type
}).then(options.success)
.catch(options.error)
}
$.ajax = function (options: any) {
return toAxiosAdapter(options)
}
$.ajax({
url: '/api/user',
type: 'GET',
success: function (data: any) {
console.log(data)
},
error: function (err: any) {
console.error(err);
}
})
let fs = require('fs');
var Bluebird = require("bluebird");
let readFile = Bluebird.promisify(fs.readFile);
(async function () {
let content = await readFile('./1.txt', 'utf8');
console.log(content);
})()
function promisify(readFile: any) {
return function (filename: any, encoding: any) {
return new Promise(function (resolve, reject) {
readFile(filename, encoding, function (err: any, data: any) {
if (err)
reject(err);
else
resolve(data);
})
});
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcss.com/vue/2.5.17/vue.js"></script>
<title>vue</title>
</head>
<body>
<div id="root">
<p>{{name}}</p>
<p>{{upperName}}</p>
</div>
<script>
let vm=new Vue({
el: '#root',
data: {
name:'zfpx'
},
computed: {
upperName() {
return this.name.toUpperCase();
}
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<select id="users"></select>
<script>
let tree = [{
name: '父亲',
key: '1',
children: [
{
name: '儿子',
key: '1-1',
children: [
{
name: '孙子',
key: '1-1-1'
}
]
}
]
}]
function flattenAdapter(tree, flattenArray) {
tree.forEach((item) => {
if (item.children) {
flattenAdapter(item.children, flattenArray)
}
flattenArray.push({ name: item.name, key: item.key })
})
return flattenArray
}
let array = [];
flattenAdapter(tree, array);
array.reverse();
let users = document.getElementById('users');
let options = array.map(item => `<option value="${item.key}">${item.name}</option>`).join('');
users.innerHTML = options;
</script>
</body>
</html>
//cnpm i sequelize sqlite3 -S
const { Sequelize, Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');
class User extends Model { }
User.init({
username: DataTypes.STRING
}, { sequelize, modelName: 'user' });
sequelize.sync()
.then(() => User.create({
username: 'zhufeng'
}))
.then(result => {
console.log(result.toJSON());
});
abstract class Shape {
abstract draw(): void;
}
class Circle extends Shape {
draw() {
console.log('绘制圆形');
}
}
class Rectangle extends Shape {
draw() {
console.log('绘制矩形');
}
}
abstract class ColorfulShape extends Shape {
public constructor(public shape: Shape) {
super();
}
abstract draw(): void;
}
class RedColorfulShape extends ColorfulShape {
draw() {
this.shape.draw();
console.log('把边框涂成红色');
}
}
class GreenColorfulShape extends ColorfulShape {
draw() {
this.shape.draw();
console.log('把边框涂成绿色');
}
}
let circle = new Circle();
let redColorfulShape = new RedColorfulShape(circle);
redColorfulShape.draw();
let rectangle = new Rectangle();
let greenColorfulShape = new GreenColorfulShape(rectangle);
greenColorfulShape.draw();
decorator
export { }
namespace decorator {
interface Animal {
swings: string;
fly: any
}
function flyable(target: any) {
console.log(target);
target.prototype.swings = 2;
target.prototype.fly = function () {
console.log('I can fly');
}
}
@flyable
class Animal {
constructor() { }
}
let animal: Animal = new Animal();
console.log(animal.swings);
animal.fly();
}
decorator_factory
namespace decorator_factory {
interface Animal {
swings: string;
fly: any
}
function flyable(swings: number) {
return function flyable(target: any) {
console.log(target);
target.prototype.swings = swings;
target.prototype.fly = function () {
console.log('I can fly');
}
}
}
@flyable(2)
class Animal {
constructor() { }
}
let animal: Animal = new Animal();
console.log(animal.swings);
animal.fly();
}
namespace property_namespace {
//实例属性target是类的原型对象,key是属性名称
function instancePropertyDecorator(target: any, key: string) {
}
//类属性target是的构造函数
function classPropertyDecorator(target: any, key: string) {
}
//实例方法装饰器target是原型对象,key方法名,descriptor是方法描述符
function instanceMethodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
}
//类方法装饰器target是类的构造函数
function classMethodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
}
class Person {
@instancePropertyDecorator
instanceProperty: string;
@classPropertyDecorator
public static classProperty: string;
@instanceMethodDecorator
instanceMethod() {
console.log('instanceMethod');
}
@classMethodDecorator
classMethod() {
console.log('classMethod');
}
}
}
let { readonly } = require('core-decorators');
function deprecate(msg: string, options: any) {
return function (target: any, attr: any, descriptor: any) {
//DEPRECATION Calculator#add: This function will be removed in future versions.
let oldVal = descriptor.value;
descriptor.value = function (...args: any[]) {
let message = msg ? msg : `DEPRECATION ${target.constructor.name}#${attr}: This function will be removed in future versions.`;
let see = options && options.url ? `see ${options.url}` : ``;
console.warn(message + '\r\n' + see);
return oldVal(...args);
}
}
}
class Calculator {
@deprecate('stop using this', { url: 'http://www.baidu.com' })
add(a: number, b: number) {
return a + b;
}
}
let calculator = new Calculator();
calculator.add(1, 2);
Aspect Oriented Programming
的缩写,意为面向切面编程create-react-app zhufeng_tract
yarn add customize-cra react-app-rewired --dev
config-overrides.js
const {
override,
addDecoratorsLegacy,
} = require("customize-cra");
module.exports = override(
addDecoratorsLegacy(),
);
jsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true
}
}
import React from 'react';
import { render } from 'react-dom';
import { before, after } from './track';
class App extends React.Component {
@before(() => console.log('点击方法执行前'))
onClickBeforeButton() {
console.log('beforeClick');
}
@after(() => console.log('点击方法执行后'))
onClickAfterButton() {
console.log('afterClick');
}
@after(() => fetch('/api/report'))
onClickAjaxButton() {
console.log('ajaxClick');
}
render() {
return (
<div>
<button onClick={this.onClickBeforeButton}>beforeClick</button>
<button onClick={this.onClickAfterButton}>afterClick</button>
<button onClick={this.onClickAjaxButton}>ajaxClick</button>
</div>
)
}
}
render(<App />, document.getElementById('root'));
export const before = function (beforeFn) {
return function (target, methodName, descriptor) {
let oldMethod = descriptor.value;
descriptor.value = function () {
beforeFn.apply(this, arguments);
return oldMethod.apply(this, arguments);
}
}
}
export const after = function (afterFn) {
return function (target, methodName, descriptor) {
let oldMethod = descriptor.value;
descriptor.value = function () {
oldMethod.apply(this, arguments);
afterFn.apply(this, arguments);
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>用户注册</title>
</head>
<body>
<form action="">
用户名<input type="text" name="username" id="username">
密码<input type="text" name="password" id="password">
<button id="submit-btn">注册</button>
</form>
<script>
Function.prototype.before = function (beforeFn) {
let _this = this;
return function () {
let ret = beforeFn.apply(this, arguments);
if (ret)
_this.apply(this, arguments);
}
}
function submit() {
alert('提交表单');
}
submit = submit.before(function () {
let username = document.getElementById('username').value;
if (username.length < 6) {
return alert('用户名不能少于6位');
}
return true;
});
submit = submit.before(function () {
let username = document.getElementById('username').value;
if (!username) {
return alert('用户名不能为空');
}
return true;
});
document.getElementById('submit-btn').addEventListener('click', submit);
</script>
</body>
</html>
abstract class Star {
abstract answerPhone(): void;
}
class Angelababy extends Star {
public available: boolean = true;
answerPhone(): void {
console.log('你好,我是Angelababy.');
}
}
class AngelababyAgent extends Star {
constructor(private angelababy: Angelababy) {
super();
}
answerPhone(): void {
console.log('你好,我是Angelababy的经纪人.');
if (this.angelababy.available) {
this.angelababy.answerPhone();
}
}
}
let angelababyAgent = new AngelababyAgent(new Angelababy());
angelababyAgent.answerPhone();
<body>
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let list = document.querySelector('#list');
list.addEventListener('click',event=>{
alert(event.target.innerHTML);
});
</script>
</body>
let express=require('express');
let path=require('path')
let app=express();
app.get('/images/loading.gif',function (req,res) {
res.sendFile(path.join(__dirname,req.path));
});
app.get('/images/:name',function (req,res) {
setTimeout(() => {
res.sendFile(path.join(__dirname,req.path));
}, 2000);
});
app.get('/',function (req,res) {
res.sendFile(path.resolve('index.html'));
});
app.listen(8080);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.bg-container {
width: 600px;
height: 400px;
margin: 100px auto;
}
.bg-container #bg-image {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="background">
<button data-src="/images/bg1.jpg">背景1</button>
<button data-src="/images/bg2.jpg">背景2</button>
</div>
<div class="bg-container">
<img id="bg-image" src="/images/bg1.jpg" />
</div>
<script>
let container = document.querySelector('#background');
class BackgroundImage {
constructor() {
this.bgImage = document.querySelector('#bg-image');
}
setSrc(src) {
this.bgImage.src = src;
}
}
class LoadingBackgroundImage {
static LOADING_URL= `/images/loading.gif`;
constructor() {
this.backgroundImage = new BackgroundImage();
}
setSrc(src) {
this.backgroundImage.setSrc(LoadingBackgroundImage.LOADING_URL);
let img = new Image();
img.onload = () => {
this.backgroundImage.setSrc(src);
}
img.src = src;
}
}
let loadingBackgroundImage = new LoadingBackgroundImage();
container.addEventListener('click', function (event) {
let src = event.target.dataset.src;
loadingBackgroundImage.setSrc(src + '?ts=' + Date.now());
});
</script>
</body>
</html>
window.innerHeight || document.documentElement.clientHeight
getBoundingClientRect().top
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Lazy-Load</title>
<style>
.image {
width: 300px;
height: 200px;
background-color: #CCC;
}
.image img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="image-container">
<div class="image">
<img data-src="/images/bg1.jpg">
</div>
<div class="image">
<img data-src="/images/bg2.jpg">
</div>
<div class="image">
<img data-src="/images/bg1.jpg">
</div>
<div class="image">
<img data-src="/images/bg2.jpg">
</div>
<div class="image">
<img data-src="/images/bg1.jpg">
</div>
<div class="image">
<img data-src="/images/bg2.jpg">
</div>
<div class="image">
<img data-src="/images/bg1.jpg">
</div>
<div class="image">
<img data-src="/images/bg2.jpg">
</div>
<div class="image">
<img data-src="/images/bg1.jpg">
</div>
<div class="image">
<img data-src="/images/bg2.jpg">
</div>
</div>
</body>
<script>
const imgs = document.getElementsByTagName('img');
const clientHeight = window.innerHeight || document.documentElement.clientHeight;
let loadedIndex = 0;
function lazyload() {
for (let i = loadedIndex; i < imgs.length; i++) {
if (clientHeight - imgs[i].getBoundingClientRect().top > 0) {
imgs[i].src = imgs[i].dataset.src;
loadedIndex = i + 1;
}
}
}
lazyload();
window.addEventListener('scroll', lazyload, false);
</script>
</html>
const factorial = function f(num) {
if (num === 1) {
return 1;
} else {
return (num * f(num - 1));
}
}
const proxy = function (fn) {
const cache = {}; // 缓存对象
return function (num) {
if (num in cache) {
return cache[num]; // 使用缓存代理
}
return cache[num] = fn.call(this, num);
}
}
const proxyFactorial = proxy(factorial);
console.log(proxyFactorial(5));
console.log(proxyFactorial(5));
console.log(proxyFactorial(5));
let count = 0;
function fib(n) {
count++;
return n <= 2 ? 1 : fib(n - 1) + fib(n - 2);
}
var result = fib(10);
console.log(result, count);//55 110
let count = 0;
const fibWithCache = (function () {
let cache = {};
function fib(n) {
count++;
if (cache[n]) {
return cache[n];
}
let result = n <= 2 ? 1 : fib(n - 1) + fib(n - 2);
cache[n] = result;
return result;
}
return fib;
})();
var result = fibWithCache(10);
console.log(result, count);//55 17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#container {
width: 200px;
height: 400px;
border: 1px solid red;
overflow: auto;
}
#container .content {
height: 4000px;
}
</style>
</head>
<body>
<div id="container">
<div class="content"></div>
</div>
<script>
function throttle(callback, interval) {
let last;
return function () {
let context = this;
let args = arguments;
let now = Date.now();
if (last) {
if (now - last >= interval) {
last = now;
callback.apply(context, args);
}
} else {
callback.apply(context, args);
last = now;
}
}
}
let lastTime = Date.now();
const throttle_scroll = throttle(() => {
console.log('触发了滚动事件', (Date.now() - lastTime) / 1000);
}, 1000);
document.getElementById('container').addEventListener('scroll', throttle_scroll);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#container {
width: 200px;
height: 400px;
border: 1px solid red;
overflow: auto;
}
#container .content {
height: 4000px;
}
</style>
</head>
<body>
<div id="container">
<div class="content"></div>
</div>
<script>
function throttle(callback, delay) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer)
clearTimeout(timer);
timer = setTimeout(() => {
callback.apply(context, args);
}, delay);
}
}
let lastTime = Date.now();
const throttle_scroll = throttle(() => {
console.log('触发了滚动事件', (Date.now() - lastTime) / 1000);
}, 1000);
document.getElementById('container').addEventListener('scroll', throttle_scroll);
</script>
</body>
</html>
<body>
<ul id="todos">
</ul>
<script>
let todos = document.querySelector('#todos');
window.onload = function(){
fetch('/todos').then(res=>res.json()).then(response=>{
todos.innerHTML = response.map(item=>`<li "><input value="${item.id}" type="checkbox" ${item.completed?"checked":""}/>${item.text}</li>`).join('');
});
}
function toggle(id){
fetch(`/toggle/${id}`).then(res=>res.json()).then(response=>{
console.log('response',response);
});
}
todos.addEventListener('click',function(event){
let checkbox = event.target;
let id = checkbox.value;
toggle(id);
});
</script>
</body>
app.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
let todos=[
{id: 1,text: 'a',completed: false},
{id: 2,text: 'b',completed: false},
{id: 3,text: 'c',completed: false},
];
app.get('/todos',function (req,res) {
res.json(todos);
});
app.get('/toggle/:id',function (req,res) {
let id=req.params.id;
todos = todos.map(item => {
if (item.id==id) {
item.completed=!item.completed;
}
return item;
});
res.json({code:0});
});
app.listen(8080);
todos.html
<body>
<ul id="todos">
</ul>
<script>
let todos = document.querySelector('#todos');
window.onload = function(){
fetch('/todos').then(res=>res.json()).then(response=>{
todos.innerHTML = response.map(item=>`<li "><input value="${item.id}" type="checkbox" ${item.completed?"checked":""}/>${item.text}</li>`).join('');
});
}
function toggle(id){
fetch(`/toggle/${id}`).then(res=>res.json()).then(response=>{
console.log('response',response);
});
}
let LazyToggle = (function(id){
let ids = [];
let timer;
return function(id){
ids.push(id);
if(timer){
clearTimeout(timer);
}
timer = setTimeout(function(){
toggle(ids.join(','));
ids = null;
clearTimeout(timer);
timer = null;
},2000);
}
})();
todos.addEventListener('click',function(event){
let checkbox = event.target;
let id = checkbox.value;
LazyToggle(id);
});
</script>
app.js
app.get('/toggle/:ids',function (req,res) {
let ids=req.params.ids;
ids=ids.split(',').map(item=>parseInt(item));
todos = todos.map(item => {
if (ids.includes(item.id)) {
item.completed=!item.completed;
}
return item;
});
res.json({code:0});
});
proxy-server.js
const http = require('http');
const httpProxy = require('http-proxy');
//创建一个代理服务
const proxy = httpProxy.createProxyServer();
//创建http服务器并监听8888端口
let server = http.createServer(function (req, res) {
//将用户的请求转发到本地9999端口上
proxy.web(req, res, {
target: 'http://127.0.0.1:9999'
});
//监听代理服务错误
proxy.on('error', function (err) {
console.log(err);
});
});
server.listen(8888, '0.0.0.0');
real-server.js
const http = require('http');
let server = http.createServer(function (req, res) {
res.end('9999');
});
server.listen(9999, '0.0.0.0');
webpack-dev-server
代理跨域otherWindow
:其他窗口的一个引用 message:将要发送到其他window的数据 message
将要发送到其他window的数据 targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URIotherWindow.postMessage(message, targetOrigin, [transfer]);
window
中传递过来的对象postMessage
时消息发送方窗口的origin
window.addEventListener("message", receiveMessage, false);
origin.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(3000);
target.js
let express = require('express');
let app = express();
let bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname));
let users = [];
app.post('/register', function (req, res) {
let body = req.body;
let target = body.target;
let callback = body.callback;
let username = body.username;
let password = body.password;
let user = { username, password };
let id = users.length == 0 ? 1 : users[users.length - 1].id + 1;
user.id = id;
users.push(user);
res.status(302);
res.header('Location', `${target}?callback=${callback}&args=${id}`);
res.end();
});
app.listen(4000);
reg.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
window.addEventListener('message', function (event) {
console.log(event.data);
if (event.data.receiveId) {
alert('用户ID=' + event.data.receiveId);
}
})
</script>
<iframe name="proxyIframe" id="proxyIframe" frameborder="0"></iframe>
<form action="http://localhost:4000/register" method="POST" target="proxyIframe">
<input type="hidden" name="callback" value="receiveId">
<input type="hidden" name="target" value="http://localhost:3000/target.html">
用户名<input type="text" name="username" />
密码<input type="text" name="password" />
<input type="submit" value="提交">
</form>
</body>
</html>
target.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
window.onload = function () {
var query = location.search.substr(1).split('&');
let callback, args;
for (let i = 0, len = query.length; i < len; i++) {
let item = query[i].split('=');
if (item[0] == 'callback') {
callback = item[1];
} else if (item[0] == 'args') {
args = item[1];
}
}
try {
window.parent.postMessage({ [callback]: args }, '*');
} catch (error) {
console.log(error);
}
}
</script>
</body>
</html>
jQuery.proxy( function, context )
function为执行的函数,content为函数的上下文this值会被设置成这个object对象<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>jquery proxy</title>
</head>
<body>
<button id="btn">点我变红</button>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
let btn = document.getElementById('btn');
btn.addEventListener('click', function () {
setTimeout($.proxy((function () {
$(this).css('color', 'red');
}), this), 1000);
});
</script>
</body>
</html>
function proxy(fn, context) {
return function () {
return fn.call(context, arguments);
}
}
拦截
,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。代理
某些操作,可以译为代理器
let wang={
name: 'wanglaoshi',
age: 29,
height:165
}
let wangMama=new Proxy(wang,{
get(target,key) {
if (key == 'age') {
return wang.age-1;
} else if (key == 'height') {
return wang.height-5;
}
return target[key];
},
set(target,key,val) {
if (key == 'boyfriend') {
let boyfriend=val;
if (boyfriend.age>40) {
throw new Error('太老');
} else if (boyfriend.salary<20000) {
throw new Error('太穷');
} else {
target[key]=val;
return true;
}
}
}
});
console.log(wangMama.age);
console.log(wangMama.height);
wangMama.boyfriend={
age: 41,
salary:3000
}
Object.defineProperty API
,Array
使用了拦截器对 Array
原型上的能够改变数据的方法进行拦截。虽然也实现了数据的变化侦测,但存在很多局限 ,比如对象新增属性无法被侦测,以及通过数组下边修改数组内容,也因此在 Vue2 中经常会使用到 $set
这个方法对数据修改,以保证依赖更新。Proxy API
对数据代理,没有像 Vue2
中对原数据进行修改,只是加了代理包装,因此首先性能上会有所改善。其次解决了 Vue2
中变化侦测的局限性,可以不使用 $set
新增的对象属性及通过下标修改数组都能被侦测到。abstract class Student {
constructor(public teacher: Teacher) { }
public abstract update();
}
class Xueba extends Student {
public update() {
console.log(this.teacher.getState() + ',学霸抬头举手');
}
}
class Xuezha extends Student {
public update() {
console.log(this.teacher.getState() + ',学渣低头祈祷');
}
}
class Teacher {
private students: Student[] = new Array<Student>();
public state: string = '老师讲课'
getState() {
return this.state;
}
public askQuestion() {
this.state = '老师提问';
this.notifyAllStudents();
}
attach(student: Student) {
this.students.push(student);
}
notifyAllStudents() {
this.students.forEach(student => student.update());
}
}
let teacher = new Teacher();
teacher.attach(new Xueba(teacher));
teacher.attach(new Xueza(teacher));
teacher.askQuestion();
原生
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>观察者模式</title>
</head>
<body>
<button id="btn">click</button>
<script>
let btn = document.getElementById('btn');
const handler1 = () => { console.log(1); }
const handler2 = () => { console.log(2); }
const handler3 = () => { console.log(3); }
btn.addEventListener('click', handler1);
btn.addEventListener('click',handler2);
btn.addEventListener('click', handler3);
</script>
</body>
</html>
jquery
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>观察者模式</title>
</head>
<body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<button id="btn">click</button>
<script>
const handler1 = () => { console.log(1); }
const handler2 = () => { console.log(2); }
const handler3 = () => { console.log(3); }
$('#btn').on('clickMe', handler1);
$('#btn').on('clickMe', handler2);
$('#btn').on('clickMe', handler3);
$('#btn').trigger('clickMe');
console.log('=================================');
$('#btn').off('clickMe', handler2);
$('#btn').trigger('clickMe');
</script>
</body>
</html>
class Promise {
private callbacks: Array<Function> = []
constructor(fn) {
let resolve = () => {
this.callbacks.forEach(callback => callback())
};
fn(resolve);
}
then(callback) {
this.callbacks.push(callback);
}
}
let promise = new Promise(function (resolve) {
setTimeout(function () {
resolve(100);
}, 1000);
});
promise.then(() => console.log(1));
promise.then(() => console.log(2));
JQuery.Callbacks
是jQuery1.7+之后引入的,用来进行函数队列的add、remove、fire、lock等操作<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
let callbacks = $.Callbacks();
let a1 = () => alert(1);
let a2 = () => alert(2);
let a3 = () => alert(13);
callbacks.add(a1);
callbacks.add(a2);
callbacks.add(a3);
callbacks.remove(a3);
callbacks.fire();
</script>
</body>
</html>
Callbacks
function Callbacks() {
let observers = [];
function add(observer) {
observers.push(observer);
}
function remove(observer) {
let index = observers.indexOf(observer);
if (index != -1)
observers.splice(index, 1);
}
function fire() {
observers.forEach(observer => observer());
}
return {
add,
remove,
fire
}
}
自定义事件
const EventEmitter = require('events');
let subject = new EventEmitter();
subject.on('click', function (name) {
console.log(1, name);
});
subject.on('click', function (name) {
console.log(2, name);
});
subject.emit('click', 'zhufeng');
events.js
class EventEmitter{
constructor() {
this._events={};
}
on(type,listener) {
let listeners=this._events[type];
if (listeners) {
listeners.push(listener);
} else {
this._events[type]=[listener];
}
}
emit(type) {
let listeners=this._events[type];
let args=Array.from(arguments).slice(1);
listeners.forEach(listener => listener(...args));
}
}
module.exports = EventEmitter;
let fs = require('fs');
let rs = fs.createReadStream('./1.txt', { highWaterMark: 3 });
rs.on('data', function (data) {
console.log(data.toString());
});
rs.on('end', function () {
console.log('end');
});
let http = require('http');
let server = http.createServer();
server.on('request', (req, res) => {
res.end('zhufeng');
});
server.listen(3000);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script>
let container = document.getElementById('root');
class Component {
state = { number: 0 }
componentWillMount() {
console.log('componentWillMount');
}
componentDidMount() {
console.log('componentDidMount');
}
shouldComponentUpdate() {
console.log('shouldComponentUpdate');
return true;
}
componentWillUpdate() {
console.log('componentWillUpdate');
}
componentDidUpdate() {
console.log('componentDidUpdate');
}
setState(newState) {
this.state = { ...this.state, ...newState }
if (!this.shouldComponentUpdate || (this.shouldComponentUpdate && this.shouldComponentUpdate())) {
if (this.componentWillUpdate)
this.componentWillUpdate();
let content = this.render();
container.innerHTML = content;
if (this.componentDidUpdate)
this.componentDidUpdate();
}
}
render() {
console.log('render');
return this.state.number;
}
}
render(Component, document.getElementById('root'));
function render(Component, container) {
let component = new Component();
if (component.componentWillMount)
component.componentWillMount();
let content = component.render();
container.innerHTML = content;
if (component.componentDidMount)
component.componentDidMount();
setTimeout(() => {
component.setState({ number: 1 });
}, 3000);
}
</script>
</body>
</html>
$on
、$emit
不方便,而你又不愿意引入vuex
,可以使用EventBus
EventBus.js
import Vue from 'vue';
export default new Vue();
组件A
import EventBus from './EventBus';
EventBus.$on("customEvent", name => {
console.log(name);
})
组件B
import EventBus from './EventBus';
EventBus.$emit("customEvent", 'zhufeng')
<body>
<script src="https://cdn.bootcss.com/vue/2.5.17/vue.js"></script>
<script>
let EventBus = new Vue();
EventBus.$on("customEvent", name => {
console.log(name);
})
EventBus.$emit("customEvent", 'zhufeng')
</script>
</body>
watcher
实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter
被调用时,会通知 watcher
重新计算,从而致使它关联的组件得以更新<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue</title>
</head>
<body>
<div id="name"></div>
<div id="age"></div>
<script>
let name = document.getElementById('name');
let age = document.getElementById('age');
class Dep {
subs = []
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach((sub) => sub())
}
}
function observe(target) {
Object.keys(target).forEach((key) => {
let val = target[key];
const dep = new Dep();
if (key == 'name') {
name.innerHTML = val;
dep.addSub(() => { name.innerHTML = val });
} else if (key == 'age') {
age.innerHTML = val;
dep.addSub(() => { age.innerHTML = val });
}
Object.defineProperty(target, key, {
get: function () {
return val;
},
set: function (value) {
val = value;
dep.notify();
}
});
})
}
let obj = { name: '名称', age: '年龄' };
observe(obj);
setTimeout(() => {
obj.name = '新名称';
}, 3000);
setTimeout(() => {
obj.age = '新年龄';
}, 6000);
</script>
</body>
</html>
export default function createStore(reducer,preloadedState,enhancer) {
if (enhancer) {
return enhancer(createStore)(reducer,preloadedState);
}
let state=preloadedState;
let listeners=[];
function getState() {
return state;
}
function subscribe(listener) {
listeners.push(listener);
return function () {
const index=listeners.indexOf(listener);
listeners.splice(index,1);
}
}
function dispatch(action) {
state=reducer(state,action);
listeners.forEach(listener=>listener())
}
dispatch({type:'@@redux/INIT'});
return {
dispatch,
subscribe,
getState
}
}
class Agency {
_topics = {}
subscribe(topic, listener) {
let listeners = this._topics[topic];
if (listeners) {
listeners.push(listener);
} else {
this._topics[topic] = [listener];
}
}
publish(topic, ...args) {
let listeners = this._topics[topic] || [];
listeners.forEach(listener => listener(...args));
}
}
class Landlord {
constructor(public agent: Agency) { }
lend(topic, area, money) {
this.agent.publish(topic, area, money);
}
}
class Tenant {
constructor(public agent: Agency, public name: string) { }
order(topic) {
this.agent.subscribe(topic, (area, money) => {
console.log(this.name, `${area}平米, ${money}元`);
});
}
}
let agent = new Agency();
let rich = new Tenant(agent, '大款');
let poor = new Tenant(agent, '北漂');
let landlord = new Landlord(agent);
rich.order('豪宅');
poor.order('单间');
landlord.lend('豪宅', 10000, 1000000);
landlord.lend('单间', 10, 1000);
SUBSCRIBE channel_a
PUBLISH channel_a zhufeng
let redis = require('redis');
let client1 = redis.createClient(6379, '127.0.0.1');
let client2 = redis.createClient(6379, '127.0.0.1');
client1.subscribe('channel_a');
client1.subscribe('channel_b');
client1.on('message', (channel, message) => {
console.log('client1', channel, message);
client1.unsubscribe('channel_a');
});
client2.publish('channel_a', 'a_hello');
client2.publish('channel_b', 'b_hello');
setTimeout(() => {
client2.publish('channel_a', 'a_world');
client2.publish('channel_b', 'b_world');
}, 3000);
Facade
是未知的class Sum {
sum(a, b) {
return a + b;
}
}
class Minus {
minus(a, b) {
return a - b;
}
}
class Multiply {
multiply(a, b) {
return a * b;
}
}
class Calculator {
sumObj
minusObj
multiplyObj
constructor() {
this.sumObj = new Sum();
this.minusObj = new Minus();
this.multiplyObj = new Multiply();
}
sum(...args) {
return this.sumObj.sum(...args);
}
minus(...args) {
return this.minusObj.minus(...args);
}
multiply(...args) {
return this.multiplyObj.multiply(...args);
}
}
let calculator = new Calculator();
console.log(calculator.sum(1, 2));
console.log(calculator.minus(1, 2));
console.log(calculator.multiply(1, 2));
class CPU {
startup() { console.log('打开CPU'); }
shutdown() { console.log('关闭CPU'); }
}
class Memory {
startup() { console.log('打开内存'); }
shutdown() { console.log('关闭内存'); }
}
class Disk {
startup() { console.log('打开硬盘'); }
shutdown() { console.log('关闭硬盘'); }
}
class Computer {
cpu;
memory;
disk;
constructor() {
this.cpu = new CPU();
this.memory = new Memory();
this.disk = new Disk();
}
startup() {
this.cpu.startup();
this.memory.startup();
this.disk.startup();
}
shutdown() {
this.cpu.shutdown();
this.memory.shutdown();
this.disk.shutdown();
}
}
let computer = new Computer();
computer.startup();
computer.shutdown();
export { }
var zlib = require('zlib');
var fs = require('fs');
let path = require('path');
function open(input) {
let ext = path.extname(input);
switch (ext) {
case '.gz':
return unZip(input);
case '.rar':
return unRar(input);
case '.7z':
return un7z(input);
default:
break;
}
}
function unZip(src) {
var gunzip = zlib.createGunzip();
var inputStream = fs.createReadStream(src);
var outputStream = fs.createWriteStream(src.slice(0, -3));
console.log('outputStream');
inputStream.pipe(gunzip).pipe(outputStream);
}
function unRar(src) {
console.log('Rar解压后的', src);
}
function un7z(src) {
console.log('7z解压后的', src);
}
open('./source.txt.gz');
function zip(src) {
var gzip = zlib.createGzip();//创建压缩流
var inputStream = fs.createReadStream(src);
var outputStream = fs.createWriteStream(src+'.gz');
inputStream.pipe(gzip).pipe(outputStream);
}
zip('source.txt');
sum.ts
function sum(a: number, b: string);
function sum(a: string, b: number);
function sum(a: any, b: any) {
return a + b;
}
export function createElement (
context: Component,
tag: any,
data: any,
children: any,
normalizationType: any,
alwaysNormalize: boolean
): VNode | Array<VNode> {
if (Array.isArray(data) || isPrimitive(data)) {
normalizationType = children
children = data
data = undefined
}
if (isTrue(alwaysNormalize)) {
normalizationType = ALWAYS_NORMALIZE
}
return _createElement(context, tag, data, children, normalizationType)
}
const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
if (__DEV__) {
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
}
Buffer.prototype.slice = function slice(start, end) {
const srcLength = this.length;
end = end !== undefined ? srcLength: srcLength;
const newLength = end > start ? end - start : 0;
return new FastBuffer(this.buffer, this.byteOffset + start, newLength);
};
export default function createStore(reducer, preloadedState, enhancer) {
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
}
function getDefaultAdapter() {
var adapter;
if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
adapter = require('./adapters/http');
} else if (typeof XMLHttpRequest !== 'undefined') {
adapter = require('./adapters/xhr');
}
return adapter;
}
jQuery.removeEvent = document.removeEventListener ?
function( elem, type, handle ) {
if ( elem.removeEventListener ) {
elem.removeEventListener( type, handle, false );
}
} :
function( elem, type, handle ) {
if ( elem.detachEvent ) {
elem.detachEvent( "on" + type, handle );
}
};
function createIterator(arr) {
let index=0;
return {
next() {
return index<arr.length?
{value: arr[index++],done: false}:
{done:true}
}
}
}
let it=createIterator([1,2]);
console.log(it.next());
console.log(it.next());
console.log(it.next());
forEach
Array.prototype.forEach = function (cb) {
for (var i = 0; i < this.length; i++) {
cb.call(this, this[i], i, arr);
}
}
let arr = [1, 2, 3];
arr.forEach((item) => {
console.log(item);
});
<body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
$.each(['1', '2', '3'], function (index, item) {
console.log(index, item);
})
$.each({ name: 'zhufeng', age: 10 }, function (index, item) {
console.log(index, item);
})
function each(obj, callback) {
if (Array.isArray(obj)) {
let length = obj.length;
for (let i = 0; i < length; i++) {
if (callback.call(obj[i], i, obj[i]) === false) {
break;
}
}
} else {
for (let i in obj) {
if (callback.call(obj[i], i, obj[i]) === false) {
break;
}
}
}
return obj;
}
</script>
</body>
next
方法顺序返回子元素Array[Symbol.iterator] = function () {
let index = 0;
return {
next: () => {
return index < this.length ?
{ value: this[index++], done: false } :
{ done: true }
}
}
}
let arr = [1, 2];
let it = arr[Symbol.iterator]();
console.log(it.next());
console.log(it.next());
console.log(it.next());
let generator = function* () {
yield 1;
yield* [2, 3];
yield 4;
};
var iterator = generator();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
class Tree {
constructor(public left, public value, public right) {
}
}
//['A', 'B', 'D','E', 'C', 'F','G']
function* leftOrder(tree) {
if (tree) {
yield tree.value;
yield* leftOrder(tree.left);
yield* leftOrder(tree.right);
}
}
//['D', 'B', 'E','A', 'F', 'C','G']
function* inOrder(tree) {
if (tree) {
yield* inOrder(tree.left);
yield tree.value;
yield* inOrder(tree.right);
}
}
//['D', 'E', 'B','F', 'G', 'C','A']
function* rightOrder(tree) {
if (tree) {
yield* rightOrder(tree.left);
yield* rightOrder(tree.right);
yield tree.value;
}
}
function make(array) {
if (array.length === 1) return new Tree(null, array[0], null);
return new Tree(make(array[0]), array[1], make(array[2]));
}
let tree = make([[['D'], 'B', ['E']], 'A', [['F'], 'C', ['G']]]);
var result: any[] = [];
for (let node of rightOrder(tree)) {
result.push(node);
}
console.log(result);
"downlevelIteration": true, / Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. /