Skip to main content

2018-2020

面向对象编程

封装

function Cat (name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function () { console.log("吃老鼠") };

// 生成实例
var cat1 = new Cat("大毛", "黄色")

构造函数的继承

function Animal() {
this.species = "猫科动物";
}
  • 构造函数绑定
function Cat(name, color) {
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
// ...
  • prototype模式
// ...
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛", "黄色");
// ...

第一行将Cat的prototype对象指向一个新Animal实例 任何一个prototype对象都有一个constructor属性指向它的构造函数。原先指向Cat,加了第一行后,指向了Animal 每个实例也有constructor属性,之后也指向了Animal

Cat.prototype.constructor == Animal; // true
cat1.constructor == Cat.prototype.constructor; // true
cat1.constructor == Animal; // true

这显然会导致继承链的紊乱,所以要加上第二行,手动纠正,将他指向Cat

  • 直接继承
  • 利用空对象继承 将Animal改写,然后建立一个空对象
function Animal () {};
Animal.prototype.species = "猫科动物";

var F = function () {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;

可以封装一下

function extend (Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Cat;
Child.uber = Parent.prototype; // 向上一层的意思,可以直接调用父对象。备用性质
}

extend(Cat, Animal);
  • 拷贝继承

非构造函数的继承

  • Object方法
var Chinese = {
nation: '中国';
}
var Doctor = {
career = "医生";
}

建立一个Object函数

function object (o) {
function F () {};
F.prototype = o;
return new F();
}
var Doctor = object(Chinese);
// 先继承,然后加上属性
Doctor.career = "医生";

页面跳转不记录历史

var urlReplace = function (element) {
if (!element) {
return;
}

var href = element.href;

if (href && /^#|javasc/.test(href) === false) {
if (history.replaceState) {
history.replaceState(null, document.title, href.split('#')[0] + '#');
location.replace('');
} else {
location.replace(href);
}
}
}

$(".link").click(function () {
urlReplace(this);
})

[].forEach.call方法

可以用于遍历document.querySelectorAll()的NodeList.

实际相当于Array.prototype.forEach.call(...)

[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ":" + item);
})
// 0:"a"
// 1:"b"
// 2:"c"

关于闭包的概念

变量的作用域

全局变量和局部变量

函数内部可以直接读取全局变量

函数外部无法读取函数内的局部变量

闭包

能够读取其他函数内部变量的函数。

"定义在一个函数内部的函数"

将函数内部和函数外部连接起来的一座桥梁

function f1 () {
var n=999;
function f2(){
return n;
}
return f2;
}
var result = f1();
result(); // 999

// f2就是一个闭包

用途:1、可以读取函数内部的变量 ;2、让这些变量的值始终保持在内存中 ;

function f1 (asd) {
var n = 999;
nAdd = function () {
n += 1
}

function f2 () {      
console.log(n);    
}
return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000

跨域

JSONP

只能使用GET请求,并要求返回javascript。 因为浏览器允许跨域引用js资源

let script = document.createElement('script)
script.src = 'http://..../login?=username=simon&callback=callback'
document.body.appendChild(script)
function callback (res) {
console.log(res)
}

CORS

浏览器需要支持HTML5 当本域向外域发起请求后,浏览器先检测外域的Access-Control-Allow-Origin是否包含本域

Nginx 反向代理

nodejs 中间件代理

可参考 https://segmentfault.com/a/1190000011145364

框架

按照情况选择框架

组件

组件树 组件可以是一个函数

  • 纯展型组件
  • 接入型组件 container
  • 交互型组件 各类加强版的表单组件,强调复用
  • 功能型组件 <router-view> <transition> 作为一种扩展,抽象机制

组件状态(state) jsx v.s. 模板

  • JSX 适合多逻辑场景
  • Javascript Templating 适合少逻辑场景 colocation
  • 该放一起的放一起 Separation of Concerns
  • 关注点分离

变化侦测和渲染机制

  • Declarative Programming 声明式编程

    描述数据跟dom的关系

  • Imperative Programming 命令式编程

    就是干,jquery式的,拿到dom下命令。不易维护。变成意大利面条式编程

  • view = render(state) 通过state数据早出view(DOM)

  • Virtual DOM

    已经有很多简单的virtual dom库

  • 通过暴力的遍历比对,来判断哪个数据变了

状态管理

  • Flux、Redux、MobX、Vuex; Rx.js

本质是 从原事件,映射到状态的迁移,映射到状态的改变,然后再映射到UI的变化。

  • Paradigm 范式,思维方式

  • cycle.js 全都是流

  • Elm

路由

  • 组件路由解耦。本质上是把url映射到组件树结构的过程

  • hash模式,history模式,兼容

  • 重定向,懒加载

  • 跳转需要钩子,取消加载使跳转无效

  • 原生app的路由,类似于3D卡片叠加的。上面的卡片关闭后,浏览看下一张卡片

css方案

  • 跟js完全解耦,靠预处理器和比如BEM这样的规范来保持可维护性,偏传统
  • CSS Modeules,通过编译来避免css类名的全局冲突
  • CSS-in-JS方案,比较激进
  • Vue的单文件组件css,或者Angular的组件css(写在装饰器里)
  • 传统css的一些问题
    • 作用域
    • Critical css 直出,(应该按需加载)
    • Atomic css 原子类css。多个class,一个基本class,再各个不同的class
    • 分发复用 放包里面
    • 跨平台复用 变成js,然后动态style绑定

构建工具

  • 解决的问题
    • 任务的自动化
    • 开发体验和效率(新语言功能,语法糖,hot reload)
    • 部署相关的需求
    • 编译时优化
  • PostHTML
  • PostCSS
  • Babel
  • AST
  • gulp,grunt等用的少了
  • wabpack

-关于部署 张云龙,讲关于部署

服务端数据通信

  • REST,围绕资源
  • Rx.js很适合处理事件
  • fetch
  • ssr

跨平台渲染

新规范

技术方案都是先有问题,再有思路,同时伴随着取舍。

调试技巧

console 调试

console.table 查看复杂对象

console.table([{a: 1, b:2}, {a: 3, b:4}])

console.time 记录运行时间

console.time('Time1'); console.timeEnd('Time1');

console.trace 获取函数的堆栈情况

console.trace()

console.todo 个性化console.log()信息

console.todo = function(msg) {
console.log('%c%s%s%s', 'color: yellow; background-color: black;', '–', msg, '–');
};
console.important = function(msg) {
console.log('%c%s%s%s', 'color: brown; font-weight: bold; text-decoration: underline;', '–', msg, '–');
};
console.todo("This is something that' s need to be fixed");
console.important('This is an important message');

将minify的代码还原

在浏览器下,点击{}来结构化代码

查看某个函数调用和其参数值

使用monitor函数可以获取到函数运行时传入的参数值。但是,有一个不足在于并没有指明该函数的形参个数

监控节点元素变化并中断

在浏览器节点上右键,Break on , 然后选定要监控的变化类型:Subtree Modifications, Attributes Modifications, Node Removal

概要

面向对象编程(OOP)

原型,继承

函数式编程(FP)

  • 纯功能
  • 避免副作用
  • 简单功能组成

类继承 和 原型继承 之间的区别

  • 类继承 : 创建紧密耦合,或层次分类
  • 原型继承:连续继承,原型委派,功能继承,对象组合

原型继承比类继承更简单灵活

函数式编程 与 面向对象编程 的优缺点

  • OOP优点: 容易理解,易于解释方法调用的含义,命令式的

  • OOP缺点: 对象和行为通常在同一个实体上被粘合。实体可能被任意数量的非确定性顺序的函数随机访问

  • FP优点: 避免任何共享的状态或副作用。 功能倾向于从根本简化并且容易重组复用

  • FP缺点: 过度使用可读性降低 简洁,但是不具体

双向数据绑定 和 单项数据流 的不同

  • 双向数据绑定 以为这UI字段被动态的绑定到数据模型上,UI改变,数据改变,反之也是 会导致难以遵循和理解的副作用

  • 数据流 数据总是单一方向流动,他是确定性的

什么是异步编程,为什么很重要

同步意味着禁止条件和函数调用,代码从上到下依次执行,阻塞长时间任务

异步意味着引擎在事件循环中运行。当需要阻塞操作时,请求被启动,并且代码保持运行而不阻塞。当响应准备就绪,就会触发中断,然后运行事件处理诚信,控制流将继续。 这样一个单线程可以处理许多并发操作

非常适合用户界面代码,有利于服务器的性能

浏览器重排(reflow)重绘(repaint)

网页生成过程

  1. HTML 被 HTML解析器解析成DOM树
  2. css 被 css解析器解析成CSSDOM树
  3. 结合DOM树和CSSDOM树,生成一个渲染树(Render tree)
  4. 生成布局(flow)
  5. 将布局绘制(paint)

重排

重新生成布局,重新排列元素

重绘

某些元素的外观被改变

webpack http-proxy 504

修改匹配的路径后面加 /**

proxy: {
'/api/**': {
// ...
}
}

浏览器往返缓存

参考 -> 浏览器往返缓存(Back/Forward cache)问题的分析与解决

// disable bfcache
try {
var bfWorker = new Worker(window.URL.createObjectURL(new Blob(['1'])));
window.addEventListener('unload', function () {
// 这里绑个事件,构造一个闭包,以免 worker 被垃圾回收导致逻辑失效
bfWorker.terminate();
});
}
catch (e) {
// if you want to do something here.
}

开发心得

更新于:2020-10-22

  • 开发移动端时,最好把状态都控制在 strore 里,你永远不知道什么时候这个组件要共享/被其他组件更新数据

  • 组件,或者页面中的单独的小子组件,可以新开一个当前组件/页面的文件夹,放在里面,你永远不知道什么时候复杂度就上来了

    - Test.jsx

    转变成

    - Test
    - index.jsx
    - TestAC.jsx
    - TestBC.jsx