javascript之高阶函数

高阶函数英文叫Higher-order function。那么什么是高阶函数?
在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:

  • 接受一个或多个函数作为输入
  • 输出一个函数

###高阶函数之把函数当做参数
JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

一个最简单的高阶函数:

1
2
3
4
5
6
function sum (x, y, f){
return f(x) + f(y)
}
```
当我们调用sum(-2,6, Math.abs)时,参数x,y和f分别接收-2,6和函数Math.abs(求绝对值),根据函数定义,我们可以推导计算过程为:

x = -2;y =6;f = Math.abs;f(x) + f(y) ==> Math.abs(-2) + Math.abs(6) ==>2+6 ;return 8

1
用代码验证一下:

sum(-2,6,Math.abs);//8

1
2
再举一个大家都熟悉的例子,Array.prototype.sort方法,接受一个函数当作参数,函数里面封装的是对数组进行排序的规则。

var arr = [1, 3, 5, 7, 2, 4, 6];
arr.sort(function(a, b) {
return a - b; //从小到大排序,如需从大到小排序,只需return b - a;
});

1
2
3
4
5
6
7
编写高阶函数,就是让函数的参数能够接收别的函数。还有常见的事件绑定回调函数,ajax回调函数等都属于高阶函数。
###高阶函数之返回值输出
在JavaScript中,函数是第一类对象,其既可以作为参数传递,也可以作为其他函数的返回值输出。
高阶函数还可作为一种模式的构造器,比如有若干排序算法(快排,冒泡,希尔等),就可以生成一个排序器。

//排序器
var sortGenerator = function(sortFunc){
return function(args){
var arguments = [].slice.call(args);
return sortFunc(arguments);
}};

1
2

//引入快速排序算法
var quickSort = require(‘quickSort.js’);
var quickSorter = sortingGenerator(quickSort);
//应用算法
quickSorter (4, 22, 44, 66, 77);

1
2
3
也许你会有疑惑我直接应用require进来的 quickSort() 就不行了。干嘛多此一举?多包装一层就可以干更多额外的事。比如测试每个排序算法的耗时。
再举个ajax封装的列子,我们写好了一个简单ajax请求服务器数据的功能,接受两个参数method和callback。请求类型和回调。每次都传入请求类型很麻烦。那么我们生成两个新的函数一个ajaxGet一个ajaxPost。

var ajaxGenerator=function(method){
return function( callback ){
ajax( method, ‘/url’, callback )
}
}
var ajaxGet=ajaxGenerator(‘get’)
ajaxGet(mycallback )

var ajaxPost=ajaxGenerator(‘post’)
ajaxPost(mycallback )
```
以上像不像函数的柯里化,是的它属于高阶函数的降阶。

webpack 使用

#WebPack是什么

  • 一个打包工具
  • 一个模块加载工具
  • 各种资源都可以当成模块来处理
  • 网站 http://webpack.github.io/
    如今,越来越多的JavaScript代码被使用在页面上,我们添加很多的内容在浏览器里。如何去很好的组织这些代码,成为了一个必须要解决的难题。

对于模块的组织,通常有如下几种方法:

  • 通过书写在不同文件中,使用script标签进行加载
  • CommonJS进行加载(NodeJS就使用这种方式)
  • AMD进行加载(require.js使用这种方式)
  • ES6模块

setup

安装命令
$ npm install webpack -g
使用webpack
$ npm init # 会自动生成一个package.json文件
$ npm install webpack –save-dev #将webpack增加到package.json文件中
可以使用不同的版本
$ npm install webpack@1.2.x –save-dev
如果想要安装开发工具
$ npm install webpack-dev-server –save-dev
$ webpack-dev-server –progress –colors
服务器可以自动生成和刷新,修改代码保存后自动更新画面
$ http://localhost:8080/webpack-dev-server/bundle

Loader

Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。

Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过 require 来加载任何类型的模块或文件,比如 CoffeeScript、 JSX、 LESS 或图片。

先来看看 loader 有哪些特性?

  • Loader 可以通过管道方式链式调用,每个 loader 可以把资源转换成任意格式并传递给下一个 loader ,但是最后一个 loader 必须返回 JavaScript。
  • Loader 可以同步或异步执行。
  • Loader 运行在 node.js 环境中,所以可以做任何可能的事情。
  • Loader 可以接受参数,以此来传递配置项给 loader。
  • Loader 可以通过文件扩展名(或正则表达式)绑定给不同类型的文件。
  • Loader 可以通过 npm 发布和安装。
  • 除了通过 package.jsonmain 指定,通常的模块也可以导出一个 loader 来使用。
  • Loader 可以访问配置。
  • 插件可以让 loader 拥有更多特性。
  • Loader 可以分发出附加的任意文件。

Loader 本身也是运行在 node.js 环境中的 JavaScript 模块,它通常会返回一个函数。大多数情况下,我们通过 npm 来管理 loader,但是你也可以在项目中自己写 loader 模块。

按照惯例,而非必须,loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 json-loader

在引用 loader 的时候可以使用全名 json-loader,或者使用短名 json。这个命名规则和搜索优先级顺序在 webpack 的 resolveLoader.moduleTemplates api 中定义。

1
Default: ["*-webpack-loader", "*-web-loader", "*-loader", "*"]

Loader 可以在 require() 引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。

接上一节的例子,我们要在页面中引入一个 CSS 文件 style.css,首页将 style.css 也看成是一个模块,然后用 css-loader 来读取它,再用 style-loader 把它插入到页面中。

1
2
/* style.css */
body { background: yellow; }

修改 entry.js:

1
2
3
require("!style!css!./style.css") // 载入 style.css
document.write('It works.')
document.write(require('./module.js'))

安装 loader:

1
npm install css-loader style-loader

重新编译打包,刷新页面,就可以看到黄色的页面背景了。

如果每次 require CSS 文件的时候都要写 loader 前缀,是一件很繁琐的事情。我们可以根据模块类型(扩展名)来自动绑定需要的 loader。

将 entry.js 中的 require("!style!css!./style.css") 修改为 require("./style.css") ,然后执行:

1
2
3
4
$ webpack entry.js bundle.js --module-bind 'css=style!css'
# 有些环境下可能需要使用双引号
$ webpack entry.js bundle.js --module-bind "css=style!css"

显然,这两种使用 loader 的方式,效果是一样的。

config

每个项目下都必须配置有一个 webpack.config.js

基本示例

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
entry: "./entry.js",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" }
]
}
}

下面是一个较完整的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
module.exports = {
//插件项
plugins: [commonsPlugin],
//页面入口文件配置
entry: {
index : './src/js/page/index.js'
},
//入口文件输出配置
output: {
path: 'dist/js/page',
filename: '[name].js'
},
module: {
//加载器配置
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.js$/, loader: 'jsx-loader?harmony' },
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
]
},
//其它解决方案配置
resolve: {
root: 'E:/github/flux-example/src', //绝对路径
extensions: ['', '.js', '.json', '.scss'],
alias: {
AppStore : 'js/stores/AppStores.js',
ActionType : 'js/actions/ActionType.js',
AppAction : 'js/actions/AppAction.js'
}
}
};

plugins 是插件项,这里我们使用了一个 CommonsChunkPlugin的插件,它用于提取多个入口文件的公共脚本部分,然后生成一个 common.js 来方便多页面之间进行复用。
entry 是页面入口文件配置,output 是对应输出项配置 (即入口文件最终要生成什么名字的文件、存放到哪里)
module.loaders 是最关键的一块配置。它告知 webpack 每一种文件都需要使用什么加载器来处理。 所有加载器需要使用npm来加载
最后是 resolve 配置,配置查找模块的路径和扩展名和别名(方便书写)

判断鼠标进入容器的方向

思路:以div容器的中心点作为圆心,以高或宽中小的值作为直径画圆,鼠标进入容器时的点的atan2(y,x)值在这四个象限里分别对应容器边框的下,右,上,左。

function direction(e){
       var w = $(this).width();
       var h = $(this).height();
       var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
       var y = (e.pageY - this.offsetTop - (h / 2)) * (h > w ? (w / h) : 1);
       var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4; //direction的值为“0,1,2,3”分别对应着“上,右,下,左”
       retrun direction
}

$(“#wrap”).bind(“mouseenter mouseleave”,function(e) {
var direction = direction(e)
});

angular2-start

第一个大的思想是一个Angular 2应用是由组件(Component)构成。组件的一种方式是教浏览器来认识新标签。
Angular 2应用无非就是一个是组件树。
在树的根部,最顶层的组件是应用本身,这就是浏览器将引导的(bootstrapping)的应用
其中一个有关组件强大的是,他们是可组合。这意味着,我们可以从较小组件来建立更大的组件。应用只是一个简单的渲染其他组件的组件。
因为组件是一个父/子树的结构,每个组件渲染时,将递归地渲染其子组件。

,