Git Product home page Git Product logo

muxfe.github.io's Introduction

Hi, I'm Kyer 👋

kyer's GitHub stats

Top Languages

Top Langs

muxfe.github.io's People

Contributors

muxfe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

zhenghuahou

muxfe.github.io's Issues

百度前端面试小记

web_interview

百度前端面试(一面)

尽管上周末百度的在线笔试非常不顺,这周一还是被通知第二天参加面试。

面试直接安排在面试官所在的宾馆房间里,单独面试,由于只参加了一面,所以只能谈谈一面的感受。

百度是个比较崇尚技术的公司,一面全程都是技术基础知识和一个编程测试,没有问任何项目经验相关的东西,感觉有点像线下笔试了。

整个面试持续了一个小时。

面试内容整理如下:

自我介绍

必须的

HTML相关

一些标签

  • 加粗
  • 上/下标
  • pre

块级元素和行内元素举例及其区别

DOCTYPE的作用

CSS布局相关

元素居中的几种方法

display分别可以取哪几个值及其相关含义

bfc ( block formatting context )

选择器优先级

盒模型

CSS预处理

JavaScript相关

5个基本类型

原型链与继承

判断变量的类型

setTimeout和setInterval

事件模型

ajax跨域

this指针和改变this指针的几种方法

一个编程题

写一个js函数,功能是将一段英文句子的所有单词首字母变成大写。

HTTP相关

基本方法

状态码及其含义

js库

jQuery

d3

svg和canvas

提问面试官

在前端如何选择技术方向深入学习

答曰:项目实践

经验教训

状态

要自信。

编程

编程能力应该是面试官非常看重的一点,这方面我在js的算法上并不十分熟练,导致编程题答得一塌糊涂。非常遗憾。

沟通

每个问题应该仔细沟通然后理解,再作答。

基础

一定要扎实。
一定要扎实。
一定要扎实。
(重要的话说三遍)

简历

我的简历上并无十分突出的东西,但是简洁、一目了然。还写上了GitHub的地址,虽然发现自己在GitHub上很水,我想面试官应该看了,这是一把双刃剑啊。

小结

总体来说,我答得有些问题并不十分准备,甚至是错误的,反映出我在项目实践方面的欠缺和基本功的不扎实。在平时项目中,对于很多知识或者问题,仅仅通过百度/google出答案然后就不再深究,也没有积累,是非常不好的。

相比今年7月份参加的阿里校招实习生的面试,我觉得自己已经进步了很多,从之前的方向不定和迷茫中渐渐找到了自己真正喜欢的东西。缺点是没有持续的学习和编码练习。

以此自勉。

在 Ubuntu 14 上使用 Git

在 Ubuntu 14 上使用 Git

之前一直用 GitHub for Windows , GUI 帮我搞定了一切,不用关心背后发生了什么,就可以随意的 commit 和 push 代码。现在换到 Linux 环境之后发现没有那么方便了,全都要自己搞,虽然麻烦,但是学到不少东西。技术的事情还是偷不得懒的。

安装 Git

$ sudo apt-get install git

安装很简单,用 Ubuntu 的 apt-get 就可以了。

身份认证

安装了 git 还是不能将代码 push 到自己的 GitHub 上面,因为还没有认证。GitHub 提供了两种主要安全的连接方式,ssh 和 https 。GitHub 官方推荐使用 https.

  • ssh 设置 ssh-key 比较麻烦,但后面使用就方便了
  • https 使用用户名和密码进行身份认证, 每次 push 都要输入

SSH 认证

SSH 使用 RSA 非对称加密算法来加密信息,下面生成与 GitHub 服务器通信认证所需的密钥。
Generateing SSH key

$ ssh-keygen -t rsa -b 4096 -C "[email protected]"

保存 key 的位置选择默认位置 ( ~/.ssh/ ) 即可,直接按 Enter 。 然后需要为这个 key 设置一个passphrase(密码),后面会用到。最后就得到一个 key 了。

加入 key 到 ssh-agent

ssh-add ~/.ssh/id_rsa

加入 key 到 GitHub 账户

首先复制 key

$ sudo apt-get install xclip

$ xclip -sel clip < ~/.ssh/id_rsa.pub

然后找到 GitHub -> Profile -> Settings -> SSH keys -> Add SSH key , 将剪贴板的内容复制到 key 里。保存即可。

验证是否添加成功

出现 Hi, username! 字样就是认证成功了。

使用 SSH 连接 push 代码

cd repo
$ git remote set-url origin git+ssh://[email protected]/[username]/[repo].git 

这样就不用每次 push 都要输入用户名和密码了。

提交和同步

将所有修改的文件加入缓存区

$ git add -A

提交修改

$ git commit -m 'message'

推送到远程版本库

$ git push

设置 push.default

$ git config --global push.default matching
$ git config --global push.default simple
  • matching All branches
  • simple Only the current branch

从远程版本库同步

$ git pull

Getting Started

p15359619

写东西对我来说一直是个很痛苦的事,想法杂乱而没有条理,想到哪是哪,所以迟迟无法下笔。

Wordpress的博客,写了两篇源码分析和一篇算法分析,感觉很好,但是没有坚持下来,一年之后我决定还是不再续费域名和虚拟主机,因为我发现了一个更好的写东西的地方,GitHub.

GitHub初识感觉是个代码云存储的东西,但实际学习才发现,GitHub已经在VCS中越来越完善和强大, 借助Linus Torvalds的盛名发展得更是如日中天。

知道这里可以写博客是一个月前,在简书上看到的一篇文章,《基于 Github Issues 的单页面静态博客》,其中借鉴了ali玉伯的GitHub Issues博客,通过调用GitHub的API来生成静态网页,非常有意思。

暑假在实验室实习,继续学习前端的东西,不敢说深入,因为还学得很浅,各种框架类库和ECMAScript的新东西,层出不穷,日新月异。想要先打好JS的基础,进而深入学习JS语言的精髓,有好的idea和疑问,会在这里记录下来,算是学习历程的一个节点。

x-web
2015/8/16 XDU SSELab

最长回文子串

最长回文子串

最近在 leetcode 上刷算法题,重温一下 ACM 和 javascript 练手,发现了一道有趣的题目,最长回文子串。

开始的想法是反转字符串然后找出最大公共子串(LCS),但是 TLE 了。觉得可能是 js 本身效率太低,然后找了 leetcode 上别人写的算法分析,发现反转后找 LCS 是错误的,而且分析写得非常好,觉得应该好好学习下,记录在此。

回文

回文字符串就是指无论从那个方向读都是一样的,如'aba'就是一个简单的回文串。

开始的想法是先将字符串反转,然后找出它们的最长公共子串,即是要找最长回文串。

然而这是错误的!!!

比如 'abadfcdaba' 反转后是 'abadcfdaba',它们的 LCS 是 'abad',这显然不是一个回文串。

而它存在的原因就是原字符串中出现了两个一样的回文串,且有额外相同的部分分别出现在这两个回文串的前后。导致反转后的字符串除了回文部分相同外,还有非回文串也相同。

下面介绍几种不同的方法来计算 LPS。

暴力搜索

最简单的办法是找出字符串中的所有子串,判断其是否为回文串,然后记录下其中最大的回文子串即可。

暴搜无例外的话效率都很低,这个算法是 O(N^3) 的。首先找出所有子串 是 O(N^2) 的,然后判断其是否为回文是 O(N) 的。

var longestPalindrome_bf = function(s) {
  if (!s) return '';
  var longest = s[0], str, i, j, len;
  var isPalindrom = function (left, right) {
    while (left < right && s[left] === s[right]) {
      left++;
      right--;
    }
    return left >= right;
  }
  for (len = 2; len <= s.length; len++) {
    for (i = 0; i < s.length; i++) {
      j = i + len - 1;
      if (isPalindrom(i, j)) {
        str = s.slice(i, j + 1);
        if (longest.length < str.length) longest = str;
      }
    }
  }
  return longest;
}

动态规划

DP可能是解这个问题的一个好方法,然而算法复杂度依然是 O(N^2) 的,而且空间复杂度也是 O(N^2)。

我们假设用 P[i][j] 来表示 s[i..j] 是否是一个回文子串。

它的计算公式长这样:

P[i][j] = s[i] === s[j] && P[i + 1][j - 1] ? true : false;

算法实现如下:

var longestPalindrome_dp = function(s) {
  var i, j, len;
  // isPalindrom[i][j] represent s[i..j] is a parlindrom string or not.
  var isPalindrom = new Array(s.length);
  for (i = 0; i < s.length; i++) {
    isPalindrom[i] = new Array(s.length).fill(false);
  }
  var maxLen = 1, longestBegin = 0;
  // initialize
  for (i = 0; i < s.length; i++) {
    isPalindrom[i][i] = true;
    if (i < s.length - 1 && s[i] === s[i + 1]) {
      isPalindrom[i][i + 1] = true;
      maxLen = 2;
      longestBegin = i;
    }
  }
  // compute
  for (len = 3; len <= s.length; len++) {
    for (i = 0; i < s.length; i++) {
      j = len + i - 1;
      if (s[i] === s[j] && isPalindrom[i + 1][j - 1]) {
        isPalindrom[i][j] = true;
        maxLen = len;
        longestBegin = i;
      }
    }
  }
  return s.slice(longestBegin, longestBegin + maxLen);
}

这个实现在 leetcode 上 TLE 了。几乎跟暴搜一样慢。

ps. 我觉得跟 js 的数组对象有关。在 js 中处理二维数组比静态语言处理要慢的多。

继续优化

降低空间复杂度

DP 的空间复杂度是 O(N^2) 的,主要用来保存二维数组 P[i][j],而且只用了一半。

我们可以把空间复杂度降到 O(1),只存找到的最长回文串即可。枚举轴心位置,并进行扩展。如果是回文,则轴心两边的字符应该对称相等。

需要考虑到长度奇偶情况的不同,如果是奇数长度,轴心就是一个字符;如果是偶数长度,轴心则不在字符串中。

实现如下:

var longestPalindrome_enum = function(s) {
  if (!s) return '';
  var longest = s[0];
  var expandAroundCenter = function (left, right) {
    while (left >= 0 && right < s.length && s[left] === s[right]) {
      left--;
      right++;
    }
    return s.slice(left + 1, right);
  }
  for (var i = 0; i < s.length; i++) {
    // 奇数
    var odd = expandAroundCenter(i, i);
    if (odd.length > longest.length) longest = odd;
    // 偶数
    var even = expandAroundCenter(i, i + 1);
    if (longest.length < even.length) longest = even;
  }
  return longest;
}

这个实现在 leetcode 上 AC 了,用了 236ms

降低时间复杂度

相比降低空间复杂度,降低时间复杂度要难得多。这里有一个 O(N) 时间复杂度的算法,叫做 Manacher 算法。

能够从 O(N^2) 降到 O(N),这个算法很巧妙。它首先解决了长度奇偶不同的问题。

通过向字符串中加入一些特殊字符来使长度均为奇数。特殊字符即为原字符串的字符集中没有的字符。如 'aba' 中插入 '#',变成'#a#b#a#'

然后提出了一个回文半径(P)的概念:

T = # a # b # a # a # b # a #
P = 0 1 0 3 0 1 6 1 0 3 0 1 0

它代表了以该字符为轴心的回文串对折后的长度。由于插入了特殊字符,如果最长回文字符串的长度为偶数,则轴心会出现在 '#' 上。

容易看出上面的例子中,最大回文子串的轴心就是 P 为 6 的字符。最大回文子串为 'abaaba' ,长度刚好为 6.

这显然不是巧合,接下来就是要计算 P,记下其最大值及对应下标,即可。目标时间复杂度 O(N)。当然,这个算法最难的部分,就是计算 P

正常计算 P 的话,时间复杂度依然是 O(N^2),但是如果利用回文串的对称特性,减少搜索,就可以将复杂度降至 O(N)

计算 P 就是以每一个字符为轴心计算回文半径,也就是从每一个字符开始向两边搜索,那么右边必然会搜索到尚未遍历到的字符,如果我们记下最大能搜索到的右边界 R
。在后面的遍历搜索中,如果当前 T[i] 在边界内,即比最大右边界小,那么也就是在一个已搜索的回文子串中,假设 i'i 对应当前最大 R 的轴心 C 的对称位置(即 T[i] == T[i']), 可以做出下面的结论:

if P[i'] < R-i
then P[i] = P[i']
else P[i] >= P[i'] (需要进一步扩展搜索得出)

另一种情况,如果当前字符 T[i] 不在边界内,即我们不能得出任何结论,所以 P[i] = 0

js 实现:

var longestPalindrome_manacher = function(s) {
  s = '^#' + s.split('').join('#') + '#$';
  var radius = new Array(s.length).fill(0);
  var C = 0, centerIndex = 0, maxRight = 0, maxLen = 0;

  for (var i = 1; i < s.length - 1; i++) {
    // 计算初始回文半径, i' = 2 * C - i
    radius[i] = (maxRight > i) ? Math.min(maxRight - i, radius[2 * C - i]) : 0;
    // 扩展半径
    while (s[i + 1 + radius[i]] && s[i - 1 - radius[i]] && s[i + 1 + radius[i]] === s[i - 1 - radius[i]]) radius[i]++;
    // 更新当前搜索的最大右边界和位置
    if (i + radius[i] > maxRight) {
      C = i;
      maxRight = i + radius[i];
    }
    // 更新最大回文串长度及位置
    if (maxLen < radius[i]) {
      maxLen = radius[i];
      centerIndex = i;
    }
  }

  return s.slice((centerIndex - maxLen), (centerIndex + maxLen + 1)).split('#').join('');
};

算法效果很好,在 leetcode 上运行时间是 160ms

以上。

有用的链接

SPA with AngularJS

Single Page Application - AngularJS

最近半年做了不少单页面网站的开发,有静态也有动态的,主要基于 AngularJS(偶尔在我的 blog
用了 ractive)。对这种重前端应用就着迷了,优点是前后端分工明确,高效(异步请求数据)且用户体验较好(没有频繁的页面跳转)。

没有任何框架能够适应一切场景。SPA 也有缺点,比如应用复杂代码量增加时,单页面应用就会有内存泄露等棘手问题,还有 SEO 优化等等问题。
SPA 适应的场景,如小型静态应用,与后台频繁交互(但不涉及重大安全问题)的应用等,我认为都是适合单页面应用的。

SPA 与 RESTful API 非常合适,只要确定接口规范,前后端开发就能较为独立地进行,前端通过 mock 异步数据,后端则直接测试接口,在前期不用集成前后端一起调试。

在此总结一下自己在基于 AngualrJS 搭建 SPA 应用的过程中学到的东西。仅限于 AngularJS 1.x。

项目结构

./
├─ src/
|   ├─ app/
|   |   ├─ [controller]/[.html, .controller.js, .css]
|   |   ├─ app.js
|   |   └─ app.controller.js
|   ├─ component/[controller]/[.html, .controller.js*, .css*]
|   ├─ fonts
|   ├─ index.html
|   ├─ 404.html
|   ├─ favicon.ico
|   └─ assets/[images, styles]
├─ dist/
├─ test/
├─ Gruntfile.js
├─ package.json
└─ README.md

应用框架

入口 - index.html

<!doctype html>
<html ng-app="simpleApp">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta charset="utf-8" />
    <title></title>
    <!-- disable caches for all browser -->
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="cache-control" content="no-store" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <meta name="viewport" content="width=device-width" />

    <!-- stylesheets start -->

    <!-- stylesheets end -->
  </head>
  <body ng-controller="MainCtrl">
    <div class="container">
      <div ng-view></div>
    </div>

    <!-- scripts start -->

    <!-- scripts end -->
  </body>
</html>

初始化 - app/app.js

'use strict';

(function () {
  var app = angular.module('simpleApp', ['ngRoute'])
    .filter('breakFilter', function() {
      return function(text) {
        if (!!text) {
          return text.replace(/\n/g, '<br />');
        }
      };
    })
    .config(function ($routeProvider, $compileProvider) {
      $routeProvider
        .when('home', {
          templateUrl: 'app/home/home.html'
        })
        .when('somepage/somepath/:someparam?', {
          templateUrl: 'app/somepage/somepage.html'
        })
        .otherwise({
          redirectTo: '/home'
        });

        // 数据绑定写入 a.href 时的白名单过滤
        $compileProvider.aHrefSanitizationWhitelist(/^(http|https|file|tel):/);
    });
})();

上面在初始化应用时添加了依赖 ngRoute ,这不是 AngularJS 原生自带的,需要单独引入 angular-route.js 文件,且必须保持与 angular.js 版本一致,否则会报错。

控制器 - *.controller.js

以 MainCtrl 为例

'use strict';

angular.module('simpleApp').controller('MainCtrl', function($scope, $http) {
  // do something
});

常用命令

ng-repeat

ng-repeat 是一个非常好用的命令,类似 forEach,能够遍历数组或对象属性,循环创建 DOM 元素。
一个简单的例子:

app.controller('SomeCtrl', function ($scope) {
  $scope.items = [{name: 'xm'}, {name: 'kyer'}]
});
<p ng-repeat="item in items">{{item.name}}</p>

ng-if/ng-show

这两个命令的用法看起来很像,都是根据属性值的真假来决定是否显示该 DOM 元素,但是有一点很重要的区别。
ng-if 值为 false 时,不会创建该 DOM 元素,而 ng-show 值为 false 时,该元素依然会被创建,只是通过设置 css 属性 display: none; 使其不显示而已。

ng-src/ng-href

由于 AngularJS 的数据替换是在脚本加载完成以后进行的,所以如果写了类似

<img src="{{data.image}}" />

其中 img 标签的 src 值会在被替换前无法正确显示图片,因为根本不存在 {{data.image}} 路径的图片文件,这时候就需要 ng-src 命令了,它会在 AngularJS
替换完数据后为 img 标签添加 src 属性,这时候就是正确的值了。

同理,ng-href 也是解决在数据替换前,a 标签的不正确行为。

一些问题的解决方法

输出 html 标签

使用 {{someHtmlStr}}ng-bind="someHtmlStr" 输出带有 html 标签的字符串时,
AngularJS 默认对其中的 html 标签做实体化转义,即将 <p>Hi</p> 变成 &lt;p&gt;Hi&lt;/p&gt;Hi,然后浏览器上看到的就是<p>Hi<p>.

AngualrJS 出于安全考虑对字符串做了过滤,但有时候我们希望输出没有实体化的 html 标签,这时候需要做一些工作。

var someHtmlStr = '<p>Hi</p>';
$scope.someHtmlStr = $sce.trustAsHtml(someHtmlStr);

$sce 服务中的 sce 是 'Stric Contextual Escaping' 的缩写,即'严格的上下文模式'。

除了上面的方式,还可以写成自定义的 filter。

app.filter('html2trusted', ['$sce', function ($sce) {
  return function (text) {
      return $sce.trustAsHtml(text);
  };
});
<p ng-bind-html="someHtmlStr | html2trusted"></p>

ng-repeat 渲染完成事件监听

有时候在一些第三方库时,会要求所需的 DOMContent 已经渲染完成,但 ng-repeat 命令渲染 DOM 和后续 js 代码执行时并行的,
我们必须监听 ng-repeat 完成时的事件,然后再对相应的 DOM 初始化第三方库。

一个比较容易理解的例子就是轮播组件,轮播内容用 ng-repeat 命令输出,但是初始化轮播时都要计算一些元素的 width/height 属性等,
由于代码是异步执行的,一旦进行了数据绑定,ng-repeat 渲染就会开始,而往往我们执行 $("#slide").slide({}) 时渲染还未完成,
就会得到不正确的显示结果。所以,轮播初始化必须在 ng-repeat 渲染完成后执行。使用 AngularJS 自定义的属性标签可以实现监听 ngRepeatFinished 事件。

app.controller('SomeCtrl', function ($scope) {
  $scope.items = [1, 2, 3];

  $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
    // do something
  });
})
.directive('onFinishRender', function ($timeout) {
  return {
    restrict: 'A',
    link: function (scope, element, attr) {
      if (scope.$last === true) {
        // $timeout 将触发事件的操作放到事件队列的最后,以保证已全部渲染完成
        $timeout(function () {
          scope.$emit(attr.onFinishRender);
        });
      }
    }
  }
});
<p ng-repeat="item in items" on-finish-render="ngRepeatFinished">{{item}}</p>

lazy-loading

在 ng-view 中渲染的 DOM 是不会解释其中包含的 script 标签的。这时候就需要用到写一个可以正常加载其中包含的 script 标签的指令。

app.directive('script', function() {
  return {
    restrict: 'E',
    scope: false,
    link: function(scope, elem, attr)
    {
      if (attr.type==='text/javascript-lazy') {
        var s = document.createElement("script");
        s.type = "text/javascript";
        var src = elem.attr('src');
        if(src !== undefined) {
            s.src = src;
        } else {
            var code = elem.text();
            s.text = code;
        }
        document.body.appendChild(s);
        elem.remove();
      }
    }
  };
});
<script type="text/javascript-lazy" src="somefile.js"></script>

这样即使在模板中写 script 标签引入外部文件,就可以正常执行了。再查了一下,发现除了 script 标签,view, controller 等都可以 lazy loading,而且这个概念也不仅局限于 AngularJS.

概念理解

依赖注入

AngularJS 使用依赖注入提高控制器代码的灵活性,通过参数名匹配注入相应的功能或服务。比如一直写的

app.controller('SomeCtrl', function ($scope, $http, ...) {
  // some code
});

参数列表中的 $scope, $http 等都是 AngularJS 原生的(前面有 $),参数列表的顺序可以是任意的,也不用列出所有可用的参数,只需选择自己用到的即可。

自己也可以定义服务、工厂函数等,AngularJS 的依赖注入机制提供了多种类型,包括

  • 值 - value
  • 工厂 - factory
  • 服务 - service
  • 提供者 - $provide
  • 常量 - constant

目前还没用过这些类型,都是自己在控制器里写相应的代码。看过一点前端的 MVC,即使用自定义工厂映射 RESTful API 对应的资源,通过对这些对象的修改,会直接 ajax 请求更新到后台,非常方便,值得学习使用。

数据绑定

AngularJS 最让人惊喜莫过于数据双向绑定了,对于表单的验证与提交,动态数据渲染 DOM 方面不能更好用了。对它的实现没有深入了解过多,
应该是用到了脏数据检查,将数据与 DOM 元素属性绑定,一旦数据修改了就更新,而且这种更新是双向的,DOM 内容可以直接修改 js 对象,js 对象值的修改也会直接反映到 DOM 中。 这块还要深入学习。

作用域

不论是前后端模板,在生成 html 内容时都有作用域的概念,如 JSP 中,通过将 <% %> 标签外的 html 代码变成字符串,标签内容代码生成 Java 代码,从而使得 JSP 页面内拥有了对应 Servlet 变量的作用域。

AngularJS 则通过 $scope 为页面模板绑定作用域,所有挂在 $scope 上的属性,可以直接在页面中使用。其中对于非 AngularJS 属性,如 hrefsrc等要使用 AngularJS 模板需要使用 {{}} 包起变量,而对于 AngularJS 的属性,则直接使用,如 ng-if="someBoolean".

AngularJS 的作用域还可以嵌套,在父作用域中定义的属性,可以在子作用域中访问。

视图

ng-view 属性用于在页面的 hashtag 发生变化时,将对应的模板渲染到该属性对应的 DOM 容器中。视图可以嵌套,不过我还没遇到过这样的开发场景。

directive

这个可能是 AngularJS 最难学的部分了,属于高手进阶关卡。在开发中遇到问题时,总是能搜到各种各样的 directive 解决方案,然而并看不懂。

首先 directive 非常强大,可以做出自定义的一套标签库,还包括自定义属性等等。而 directive 就提供了解析和处理这些自定义标签/属性等的操作。

我的相关项目

参考链接

2015年终总结

回顾2015

学业

从大三开始转向学习准备保研开始,终于在 2015 年如愿以偿.

之前一直在找工作和上研中纠结,最后还是打算上研,除了获得专业技能的提高之外,还需要更全面地学习和更好的发展.

在此回顾一下自己的 2015.

技术

前端

3 月份有面试阿里的实习生,第一次面试到二面被刷,感觉还是很不爽的.发现自己的能力和亮点还是不够突出,通过小一年时间的学习和开发实践,可以说进步了很多.

从不了解 nodejs, AMD/CMD 等等,到现在已经用 nodejs 做了一个课程项目, 不仅了解了 AMD/CMD, 还对前端业界一些新框架和新技术也有所了解,尝试了 Angular. 其他如前端的工程化,测试,组件化等非常多的东西可以去"玩".

前端技术的变化真的非常快,框架类库层出不穷,学习起来有时候也让人感到迷茫.多学习标准和**,不变的东西,经得起时间考验的东西才最有价值.

算法

大三下学习了算法导论,对一些经典算法和算法分析有了基本的认识,但是因为很久没有刷题了,算法实现能力下降很多.上个月开始坚持刷 leetcode, 然后用 github 打卡, 感觉想要每天坚持一件事真的很难.

Java

我所在的实验室主要使用 Java 语言,需要把它作为后端开发的主力.今年做了几个 Java Web 的项目练手,对 Java 只能说不喜欢也不讨厌.Java 的跨平台特性确实很诱人,现在把开发平台转到 Linux 上,所有 Java 项目都能无缝衔接.当然前端的东西本来就是平台无关的~2333.

Nodejs

看完朴灵大大的 <深入浅出 Nodejs> 后,对 Nodejs 开发更是深深地痴迷.js 语言的灵活配合 Node 的异步 IO 和事件驱动简直完美.大四上的项目管理课需要开发一个类似淘宝的电商网站,我用 Nodejs + Express + Mongodb 完成了开发,感觉很好.12 月份还看了桑大的 koa-generator-examples.发现有这么多方法来保持异步编程的优雅,缩小与同步编程的差异,感觉又要学习一波了.

可视化: D3 与 mxGraph

1 月份在实验室实习的时候,因为项目需要学习了一点 mxGraph,但是只接触了皮毛,不够深入.

8 月份实习时,学习了 D3,一个更强大的可视化 js 库,支持各种图表.主要学习和使用了饼图,引力图.也对 SVG 有了些许了解.

GitHub

Git 是一个出色的分布式版本控制工具,GitHub 则是一个神奇的网站,各大开源项目聚集地,GitHub Pages , Git Book 等等.2015 年在 GitHub 上连击了 40 天,是做项目管理那个项目的,想要坚持提交代码,无奈没有成功.2016 要好好使用它.

读书

  1. JavaScript 语言精粹
  2. Nodejs 权威指南
  3. jQuery in Action
  4. 人月神话
  5. 暗时间
  6. 深入浅出 Nodejs
  7. D3 数据可视化实战手册
  8. Nodejs 实战
  9. MongoDB权威指南

其他

常去的网站

  1. 知乎
  2. CNode
  3. GitHub
  4. V2EX
  5. Google
  6. 阮一峰的网络日志
  7. Leetcode

理财

考了证券从业资格基础知识和交易两门.

Weekly Report

2016-07-10 周日

  • 完成我的本科毕业论文

    勉勉强强完成了论文,有很多点都没写好,但还是学到很多东西。一直做工程较多,对于研究型内容有些力有不逮,还是源于基础不够扎实,持续学习很重要。

  • 研究方向调整

    由于社交网络用户影响力评价标准不一,难以有效说明,所以暂时搁置了这方面研究,转而研究学术网络下的影响力。

  • Angular - SAP

    从开始接触 Angular 开始,就对数据双向绑定、前端路由等特性着迷,前端发展早已不可同日而语。自己也用 Angular 做了几个项目,结合 bootstrap,weui 来做 UI,Grunt 做编译压缩,目前只有测试还没写过,未来学习 karma 测试框架也是任务之一。还有 React 和 Vue 诱惑着我,前端简直学无止境啊。

  • jqGrid

    在帮实验室同学做一个快速开发项目时,发现了 jqGrid 这个表格框架,基于 jQuery 实现,功能几乎无所不包,尤其适合与后端 CRUD 接口整合,大大减轻了前端开始任务。世上没有完美的东西,这个框架的确点就是文档不全,资料很少,不过貌似是闭源的,也没什么说的了。

小记

很久没有更新这里,总是瞎忙,忙毕业,忙项目,忙聚会。本科生活结束,硕士生活开始;迷茫生活结束,奋斗生活开始……

2016-05-29 周日

  • 写毕业论文

    写了 93%,剩最后关键的实验部分。

  • 修改对比算法

    修改 IC Model, TwitterRank 和 Topic-sensitive 相应的实现。之前存在一些错误。

2016-05-22 周日

  • 写毕业论文

    第一次写论文还没找到套路,在艰难的凑字数。

  • 完善和修改 cnki-crawler

    在慢慢摸索中学会了用 selenium-webdriver 这个库所支持的 promise 来实现异步流程控制,从而解决了大部分问题。在 github 和 stackoverflow 上也查了很多资料,因为 nodejs 版本的资料相对较少,一度想要放弃,但还是坚持解决了所有问题。为自己点赞~^_^

  • 验证各个算法结果

    结果不是很理想,对论文中自己的算法理解不是非常到位。

2016-05-15 周日

  • 做论文相关的实验

    因为盲审的紧逼暴露出之前实验的许多问题,实验算法实现的小问题和验证结果的不理想,都没能充分考虑和解决。深感无奈。

  • cnki-crawler

    刚开始先学习了 selenium-webdriver 这个框架,在其简单的 doc 和 stackoverflow 的基础上总算掌握了基本使用。但是因为异步的原因,有些问题总是解决不掉。如 alert 弹窗处理和窗口切换与关闭出现的问题等等。

2016-05-08 周日

主要工作

  • 测试微博数据

    • Indegree
    • TunkRank

    这两个算法最简单,也顺便测试重构后框架的易用程度。

  • 使用 GibbsLDA++-0.2 处理数据

    将较大的文本分割后进行递增地处理。

  • 整理毕设相关的东西到 github

  • 学习 python 爬虫

    写了简单的爬 api 的代码。尝试针对下载知网数据,使用爬虫进行模拟登录并下载,未果。

小记

随着夏天到来,人也变得躁动,不能静下心来编码和读书,总是时断时续。还有两周就得完成毕设论文了,还有实验室的一些工作要做,感觉自己的效率真的是太低了。开始爱上了健身,希望身体和心灵都在路上。

2016-05-01 周日

主要工作

  • 处理微博数据

    • 数据量大,约 120 GB 原始数据
    • 在 Ubuntu 14.04 LTS 上,MongoDB 3.2.4 表现很差(暂不知道原因)
    • 分词和吉布斯采样及后续算法很耗时,难以并行

    放弃使用 Mongodb,直接文件流处理,使用 JSON 的 Jar 包,逐行解析和筛选。

  • 解决 LDA Gibbs Sampling 在大数据上的问题

    使用 GibbsLDA++-0.2 处理,可以在之前的训练集上推演新的数据集,做到增量 LDA.

2016-04-24 周日

主要工作

  • 写 rosenjx 的文档

    第一次写文档,感受到要把自己熟悉东西介绍给完全不了解这方面的人,是件很难的事情。这才理解了文档能力的重要性。每个人的知识体系和价值观都不完全相同,要让别人了解自己做的东西,需要换位思考和对自己作品充分的研究,才能向别人道出其中原委。

  • 测试 Twitter 数据

    测试简单算法,重构了一下代码结构,使用 DataModel 类来屏蔽掉算法输入数据多样性。

    • InDegree
    • TunkRank

    其他算法需要 LDA Gibbs Sampling ,还不能实验。

  • 看阮一峰老师的 JavaScript 笔记

    http://javascript.ruanyifeng.com/

小记

这周毕设总算推进了,首先做了两个简单的算法实验,从数据处理,算法结果,到验证结果,全部跑通。其中还有一些问题,如验证算法速度慢,和对不同数据源,不同数据结构,不同算法,怎样写代码可以让以后跑实验的改动最小等等。

co-author 数据已经发现可以爬 Aminer.org 的网站 api 接口,因为网络问题,还没有完全得到。得到之后需要按照论文你的采样算法来采样处理,不确定性太多,需要大量时间投入。

2016-04-17 周日

主要工作

  • 理解和修改 LDAGibbsSampling
  • 用 angular 重写实验室网站模板
  • 外包网站基本完成

小记

这周很累,在 angular 开发上可以说又进了一小步,还是很开心。

首先说在项目构建上,我开始变得不太喜欢用 bower ,因为在用 grunt-usemin 的时候,不能细粒度地控制编译 js 库。重写实验室网站的时候就只直接用 npm 管理了前端库,但是 npm 也有问题,依赖太多,前后端库分不开等等,node_modules 目录下是把所有以来展开了,这样做有好处,却令人看起来很杂乱,不如 bower 那么清爽。

然后,在久试不通之后,果断放弃了用 jquery-carouFredSel.js,虽然它很强大,但真的不适合我。换了 bootstrap 来做轮播,代码清爽了很多,不用写 js。

毕设在这周进展寥寥,理解了 LDA Gibbs Sampling 之后,还需要进一步修改,以使用它。

加油。

2016-04-10 周日

主要工作

  • 处理 Twitter 数据,自然语言处理和吉布斯采样

    自然语言处理用了 nltk 完成,吉布斯采样因为内存限制还没有结果。

  • Angular-static-single-page

    • 使用 bower 和 grunt 构建项目
    • 添加了 markdown 支持
    • 修改 IE 下兼容性问题

    由于 Angular 对 DOM 的管理,导致很多意想不到的问题,在解决的时候也倍觉棘手,深感自己在原理、底层上功夫过浅。

小记

这周在 Angular-static-single-page 这个项目上花费了很多精力和时间,主要解决 Angular 封装带来的资源或库的问题,如脚本运行的时机,资源加载时机造成的脚本运行结果顺序不对,ng-repeat 渲染完成的事件问题,$scope 层级问题等等。

抓狂中也学习了不少东西,包括 Grunt 编译压缩整个项目,使用起来像 make 工具,提供了非常丰富的插件来完成各种任务。但是也有一些实际问题,如 grunt-usemin 在 build html comment bower 时,会将 bower 管理的所有依赖都编译进去,像 html5shiv.js 这样应该放在注释里以兼容 IE 的做法就难以实现;还有 grunt-contrib-uglify 在编译 js 文件时,会有是否兼容 IE8 的选项,如果是 true ,那么将会出现如 this.thisa.class 等此类压缩后不兼容 IE8 的代码,因为 thisclass 都是保留字,在 IE8 中会报错。而如果是 false ,上面的代码就会变成 this["this"]a.className

2016-04-03 周日

主要工作

  • 修改 Zeppelin 二进制包中的源码,添加新功能或新可视化图表

    按照这个 #issue 添加地图功能

  • 帮师姐跑实验

    服务组合论文相关实验,主要是配置文件很多,每次都要手动修改,然后运行。尝试自动跑程序失败,推测是工程依赖的 dll 文件的问题。

  • Angular-static-single-page

    一个用 Angular 做静态模板及单页面路由的小项目。完成了初步的模板拆分和路由配置等。

  • 读书

    《JS 高级程设》,《用 AngularJS 开发下一代 Web 应用》

小记

通过修改添加 zeppelin 地图扩展,对 zeppelin 前端结构有了深入一些的认识。因为接触过 Angular 开发,上手也较为容易。

然后在一个外包项目中使用了 zeppelin 前端框架结构,不过改成了 Angular 静态单页面路由的形式,将页面不同模块拆分、复用。上手容易,但是 Angular 做静态模板还是有点不够灵活。比如 ngInclude 的限制,IE 下的兼容性,ngInclude 模板中对 scripthtml 代码安全的限制,ngInclude 模板中如果有 h5 标签,通过引入 Google 的 html5shiv.js 不能解决这个问题等等。

感觉 Angular 还是适合表单等交互性 Web 应用,以充分体现其双向绑定的优点。

ps.拖延症犯了,坚持不是一件容易的事。2016/4/12.

2016-03-27 周日

主要工作

  • 阅读 Zeppelin 前端源码

    index.html :

    • 引入项目所依赖的静态文件( css, js, image 等)
    • angular-include 其他模板或components
    • 使用 WebSocket 进行异步通信
    • 每个 component 对应的 controller 来处理诸如交互,展示等任务

    粗看了所有代码,对 WebSocket 部分的通信和事件了解的不是很清楚。准备进一步阅读。

  • github-issue-blog 发布我的博客

    原作者用 Ractive 写的实现,我简单学习了下,很容易上手,静态单页面的路由也是第一次见到,对于一些整体布局改变不大,但是频繁交互的页面来说非常有用,单页面应用对 js 内存泄漏应该也有很好处理机制,最近学的 Zeppelin 也算一个单页面应用吧,用 AngularJS 实现,模块化组织,也很清晰。

  • 整理 Twitter 数据

    由于 Twitter 的转发评论与微博设计不同,所以在整理 Twitter 数据时遇到一些难题,如找出转发某条 tweet 的所有人。

    这周解决了推文中包含的转推关系,包括不同转推格式(如,RT @name/RT@name:)和多次转推展开等,使用正则表达式匹配,捕获分组来获取(转发格式:被转发人:被转发推文)。然后使用 Redis 作为缓存,以(作者+推文)为键,(推文编号)作为值形成一个 Hash table,以便统计转推关系。

小记

看了 github-issue-blog 和 zeppelin 的前端代码,有了对实验室模板代码进行模块化组织和单页面静态路由的想法,准备下周有时间去做。这周还玩了下 Docker ,出现各种问题,很受挫,尤其是查尽资料解决不了问题那种抓狂的感觉,还需要磨练。

之前面对毕设项目中存在的问题有点消极,没有很主动地去解决,对毕设的态度自然决定了毕设的质量,回头看自己的毕设内容,我共享的部分主要是代码实现,对原有算法的改进和思考则鲜有。总是想学习新的有趣的技术,忽略了”正务“,是浮躁和缺乏思考的表现。

换到新的环境已近一个月,各方面都稳定下来,也在融入这个实验室。在学习,生活,技术和个人提升方面还有很多要做的。

2016-03-20 周日

主要工作

  • 熟练搭建 Zeppelin 环境(单机)

    Centos 环境搭建的话,总会出现个 databind 的错误,查了发现是 jackson 包在编译时选择的版本不对,但是由于网络等原因,用 Maven 构建总是失败,只能换到 Ubuntu 14.04 中搭建。

  • 了解 Zeppelin 前后端架构

    Zeppelin 在前端主要使用了 AngularJS ,在交互方面表现很好,可视化使用 nvD3 ,构建工具使用了 npm, grunt 和 bower ,UI 使用 Bootstrap,js 兼容库使用 jQuery。

    后端主要使用 java 开发,用了 Jetty 和 Jersey 两个框架来实现 WebSocket , RESTful API 等功能。

  • 实现一个简单的 Zeppelin Interpreter

    仿照 Markdown Interpreter 的写法,自己编译打包了一个简单的 myInterpreter,将输入加上 %text 后再输出,了解了 Interpreter 的创建方法和工作原理。

  • 在阿里云搭建 实验室主页

    阿里的云翼计划 ¥10/月 可以租用一个配置不错的 ECS,用来搭建实验室的静态主页绰绰有余。

小记

这学期主要有两个项目,一个毕设,一个实验室一起做的大数据平台。

毕设在上学期进行到数据集准备和算法测试阶段,由于算法存在问题,数据集不完善,毕设项目遇到了不小的阻力,后面要在毕设上多下功夫,解决问题。

大数据平台项目我所在的小组主要负责前端部分,即支持交互式的数据查询与分析的 Apache Zeppelin 项目,学习,运用和修改它。通过粗略地阅读项目,对 Zeppelin 有了大致的了解,这个项目由于还在孵化期,使用的构建技术和框架较为前沿,学习的点很多,包括前端的可视化,angular,后端的 Jetty 和 Jersey 框架等。了解它如何运作还需要一定的积累。

业余时间看书时间变少,简单的健身和背单词效果平平,更多的刷社交网络和碎片化的知识并不是一个好的提升自我的手段,需要不断给自己施加压力。

2016-03-13 Sun

Main Work

  • [Big Data Platform] Install and Use Zeppelin

    And previously install Hadoop 2.6.4 and Spark 1.6 envirment on Ubuntu 14.04 LTS (Single-Node)

  • [Social Network] Learn and Use Klout API

  • [Other] Reinstall OS, build some development envirment

  • [Life] Work in Lab

  • [Life] Start Exercise

Note

Record my work and thought weekly.

shell 脚本编程二三事

bash

今天在 Ubuntu 的 bash 上卡了一天,最后发现竟然是一个很简单的问题。记录下来,也顺便发现自己在开发和学习上的不足。

最近实验室在开发一个 Nodejs 的容器应用,用于管理 Node 项目,使用 Java 语言,实现不同平台的应用。简单的想法是给每个项目写一个脚本,然后通过脚本来实现安装,启动和关闭等操作。Windows 的 bat 脚本写的很少,之前在《鸟哥私房菜》上学过一点 bash 的写法,就先在 Linux 平台上进行测试。

一开始脚本测试都正常,在终端可以实现完整的操作。但是在 Java 代码里就出问题了,查到构造 Linux 环境下的启动外部程序的过程是构造命令字符串,然后调用 /bin/sh -c some_command 来执行。但是测试代码始终执行不了我写的脚本。这就头大了。

都是这个 -c 参数让我吃了很多苦头。先是查不到它的作用,后来才想到应该先 man 的。man 了之后发现还是看不懂它的意思。

发现在项目目录下,执行

$ sh -c 'app.sh start'

总是报错,app.sh not found. 但是执行

$ sh -c 'ls -l'

就可以。

Google 了很多都是说权限问题或者 #!/bin/sh 之类的,完全不是我要得答案。再仔细想了一下结果,发现了问题所在。

因为 -c 参数是让 sh 要执行的指令和参数从后面给的 command_string 中获取,但是!是重新开一个 shell 来执行。也就是说后面的命令字符串是在一个新 shell 中执行。没有使用 sh app.sh./app.sh 导致找不到可执行文件。而且 ./ 的方式不能用在绝对路径中。

最后 Linux 下的测试全部通过了,明天开始写 bat 脚本,然后要对这块重新整理,学习一下。

to be continued...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.