2017.12.15-2017.12.30

JSON Schema

参考文献:https://www.cnblogs.com/wade-xu/p/4662127.html

JSON Schema 定义:

JSON Schema: 是基于JSON 格式定义JSON数据结构的规范。
用处:

  1. 描述现有数据格式
  2. 完整的结构验证,有利于自动化测试。
  3. 完整的结构验证,可用于验证客户端提交的数据。

基本Json Schema

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "User",
  "description": "demo schema",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string"
    },
    "LastName": {
      "type": "string"
    },
    "age": {
      "description": "Age in years",
      "type": "integer",
      "minimum": 0
    }
  },
  "required": [
    "firstName",
    "LastName"
  ]
}
2017.12.15-2017.12.30_第1张图片
image.png

如何测试JSON Schema

使用JSON Schema validator GUI
地址 http://json-schema-validator.herokuapp.com/


何为MongoDB

MongoDB 是基于文档存储(而非表),是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

何为Mongoose?

简单的说,Mongoose就是对node环境中MongoDB数据库操作的封装,一个对象模型工具,将数据库中的数据转换为javaScript对象以供我们在应用中使用。

Mongoose 的Model层API大致分为:创建(Create)、更新(Update)、读取(Find)和删除(Remove)四类,create 和 remove操作返回promise对象,update和find操作返回query对象。对于query对象,只需要对其调用exec方法,就可以返回promise对象了。

Schema

Schema是一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。
如何创建一个Schema?

const Articles = new Schema({
  articleId: {type: string},
  title: {type: string},
  content: {type: string}
}, {collection: 'articles'})

第一个参数是结构对象,每一个键就是一个字段,你可以定义类型/默认值/验证/索引等;第二个参数是可选的(默认是取model的第一个参数加s), 用来自定义Collection的名称。
当然也可以这样定义名称:

mongoose.model('articles', Articles, 'articles');

注:我们不需要收到去创建Collection, 当你操作时,如Collection不存在,会自动创建。

Model

由Schema发布生成的模型,具有抽象属性和行为的数据库操作对象。正是Model的存在,让我们操作数据库更加方便快捷。
依赖Schema 生产一个 Model:

mongoose.model('articles', Articles);
Entity

由Model创建的实体,它的操作也会影响数据库。
依赖model, 创建一个Entity

const article = newe ArticlesModel();

Vuex

vuex 是一个专为Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。


MVVM:
MVC:
  • View 用来把数据以某种方式呈现给用户
  • Model 其实就是数据
  • Controller 接收并处理来自用户的请求,并将Model 返回给用户
为什么前端要工程化,要使用MVC? http://web.jobbole.com/88931/

相对 HTML4 , HTML5 最大的亮点是它为移动设备提供了一些非常有用的功能,使得 HTML5 具备了开发App的能力, HTML5开发App 最大的好处就是跨平台、快速迭代和上线,节省人力成本和提高效率,因此很多企业开始对传统的App进行改造,逐渐用H5代替Native,到2015年的时候,市面上大多数App 或多或少嵌入都了H5 的页面。

既然要用H5 来构建 App, 那View 层所做的事,就不仅仅是简单的数据展示了,它不仅要管理复杂的数据状态,还要处理移动设备上各种操作行为等等。因此,前端也需要工程化,也需要一个类似于MVC 的框架来管理这些复杂的逻辑,使开发更加高效。

这种 MVC 架构模式对于简单的应用来看起是OK 的,也符合软件架构的分层思想。 但实际上,随着H5 的不断发展,人们更希望使用H5 开发的应用能和Native 媲美,或者接近于原生App 的体验效果,于是前端应用的复杂程度已不同往日,今非昔比。这时前端开发就暴露出了三个痛点问题:

  • 开发者在代码中大量调用相同的 DOM API, 处理繁琐,操作冗余,使得代码难以维护。
  • 大量的DOM操作使页面渲染性能降低,加载速度变慢,影响用户体验。
  • 当Model频繁发生变化,开发者需要主动更新到View; 当用户的操作导致Model 发生变化,开发者同样需要将变化的数据同步到Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。
    MVVM 的出现,完美解决了以上三个问题。

MVVM 由 Model,View,ViewModel 三部分构成,Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

Vue

  1. Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统。
  2. 数据和DOM建立关联后,所有东西都是响应式的。
  3. v-model指令,实现表单输入和应用状态之间的双向绑定。

toLocaleDateString

toLocaleDateString() 方法可根据本地时间把 Date 对象的日期部分转换为字符串,并返回结果。

new Date().toLocaleDateString()

H5 开发APP

HTML5开发App最大好处是:跨平台、快速迭代、快速上线。

函数防抖与节流:

函数节流:强制规定一个函数在一段时间内能够被执行的最大次数。
函数防抖:某个函数在上一次执行后,满足等待某个时间内不再触发此函数后再执行,而在这个等待时间内再次触发此函数,等待时间会重新计算。

纯函数

纯函数:相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

slice(start, [end]) 
1 从已有的数组中返回选定的元素。
2 返回值:返回一个新的数组,包含从start 到 end (不包括该元素) 
3 ps: 该方法不会修改数组,而是返回一个子数组。如果想删除数组中的一段元素,应该使用方法:Array.splice()。

splice(index, howmany, [item1, item2]) 
1 向数组中添加项目或者从数组中删除项目,然后返回被删除的项目。
2 返回值:包含被删除项目的新数组,如果有的话
3 ps: 该方法会修改原数组。

柯里化

参考文章:https://github.com/dreamapplehappy/hacking-with-javascript/blob/master/books/javascript-the-good-parts/chapter-4-function/currying.md
维基百科中对柯里化的定义:柯里化是一种将使用多个参数的函数转换成一系列使用一个参数的函数的技术
《JavaScript设计模式与开发实战》:一个柯里化函数首先会接受一些参数,但是接受这些参数后,该函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。等到函数被真正需要求值的时候,之前传入的所有参数会被一次性用于求值。
柯里化的作用之一:提前返回
使用场景:

  • 延迟计算
  • 参数复用
  • 动态创建函数。这可以是在部分计算出结果后,在此基础上动态生成新的函数处理后面的业务,这样省略了重复计算。或者可以通过将要传入调用函数的参数子集,部分应用到函数中,从而动态创造出一个新函数,这个新函数保存了重复传入的参数(以后不必每次都传)。例如,事件浏览器添加事件的辅助方法:

下面是一个增量处理函数。属于参数复用和延迟计算的混合。fn作为Handler会在最后接收到所有传入过的参数,然后做统一处理。

var currying = function (fn) {
    var _args = [];
    return function () {
        if (arguments.length === 0) {
            return fn.apply(this, _args);
        }
        Array.prototype.push.apply(_args, [].slice.call(arguments));
        return arguments.callee;
    }
};

下面是一个跨浏览器事件注册例子,第一次计算为判断浏览器支持类型,然后返回一个函数用来后续的计算过,因此第一次的计算可以被服用,不需要再次调用。
原本写法:

var addEvent = function(el, type, fn, capture) {
     if (window.addEventListener) {
         el.addEventListener(type, function(e) {
             fn.call(el, e);
         }, capture);
     } else if (window.attachEvent) {
         el.attachEvent("on" + type, function(e) {
             fn.call(el, e);
         });
     } 
 };

柯丽化之后写法:

var addEvent = (function(){
    if (window.addEventListener) {
        return function(el, sType, fn, capture) {
            el.addEventListener(sType, function(e) {
                fn.call(el, e);
            }, (capture));
        };
    } else if (window.attachEvent) {
        return function(el, sType, fn, capture) {
            el.attachEvent("on" + sType, function(e) {
                fn.call(el, e);
            });
        };
    }
})();

按照之前的写法,我们每次使用addEvent为元素添加事件的时候,都会走一遍if...else if ... 分支,其实只要一次判定就可以了。柯里化函数在第一次进入分支之后,会在函数内部动态生成新函数,以后就不必重新计算。

给setTimeout 传递进来的函数添加参数

1 使用匿名函数包裹我们要执行的函数,然后再函数体里给那个函数传递参数值

function hello(name) {
  console.log('hello, ' + name);
}

setTimeout(hello('dreamapple'), 3600); //立即执行,不会在3.6s后执行
setTimeout(function() {
  hello('dreamapple');
})

2 使用bind方法 其原理其实也是使用了柯里化

setTimeout(hello.bind(this, 'dreamapple'), 3600);

3 柯里化

setTimeout(curryingHelper(hello, 'dreamapple'), 3600);

Meta


Console的一些API

console.table: 将数组内容以表格的形式将数据展示出来,方便查看数组的内容
console.count: 记录方法执行的次数
console.time && console.timeEnd 记录代码的执行时间

原型到原型链

1 每个函数都有一个prototype属性,就是我们经常在各种例子中看到的那个prototype。
2 函数的prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型。
3 什么是原型呢?你可以这么理解:每一个JavaScript对象在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每个对象都会从原型上"继承"属性


2017.12.15-2017.12.30_第2张图片
image.png

4 那实例 和 实例之间如何表示?那就需要第二个属性:proto
每一个JavaScript对象都具有一个属性,叫proto, 这个属性会指向该对象的原型。

2017.12.15-2017.12.30_第3张图片
image.png

5 实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或实例呢?
指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的。这就需要第三个属性:constructor, 每个原型都有一个constructor 属性指向关联的构造函数。


2017.12.15-2017.12.30_第4张图片
image.png

6 原型的原型
在前面我们讲了,原型是一个对象,既然是对象,我们就可以用最原始的方式创建它,如:new Object();
其实原型对象就是通过Object 构造函数生成的,结合之前所讲,实例的proto指向构造函数的prototype, 所以我们再更新下关系图:

2017.12.15-2017.12.30_第5张图片
image.png

7 原型链:


2017.12.15-2017.12.30_第6张图片
image.png

一个小结论:
最后总结:先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生。

参考文章
https://github.com/creeperyang/blog/issues/9
https://github.com/mqyqingfeng/Blog/issues/2

你可能感兴趣的:(2017.12.15-2017.12.30)