Andre Huang


  • 首页

  • 归档

JavaScript 变量声明提升

发表于 2016-08-21

在 JavaScript 中,变量声明和函数声明会被引擎隐式地提升到当前作用域的顶部。

如:

var b = 1;
function a() {
console.log(typeof b);
var b = 3;
}
a();

输出的结果会是:undefined. 而不是 1。

这就是因为变量 b 的声明被提前了,typeof 操作符操作的变量不是全局变量 b;而是待赋值的局部变量 b。

同理,函数的声明也如此:

var foo = function(){
console.log(1);
}
function f1() {
console.log(typeof foo); // "function"
}
function f2() {
console.log(typeof foo); // "undefined"
var foo = function(){
console.log(2);
}
}

但是直接定义的话就不会为 undefined。

(function(){
console.log(foo);
function foo(){
console.log("this is ain't a function for the broken-hearted.");
};
})();

附上两道据说2014年阿狸笔试题:

var v = "Hello world";
(function() {
console.log(v);
var v = "I love you";
bar();
foo();
function bar(){
console.log("this is bar!");
}
var foo = function() {
console.log("this is foo!");
};
})();
// Result: undefined; "this is bar!"; foo is not a function
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
alert(typeof bar());
// Result: "function"

使用 Express 框架来开发 Node.js 应用

发表于 2016-04-10

前(che)言(dan)

由于毕业设计想尝试着使用 Node.js 来做一个应用,因此便接触了 Express 这个已有的 Web 开发框架。
有了 Express 这个框架,就可以省去自己手动实现小到一个 POST 请求,大到 Cookie、会话的管理的精力,避免了重复造轮子。

Express 实现的功能

  • 为 http 模块提供了更高层的接口,而不用直接使用 Node.js 的 http 模块提供的底层接口
  • 路由控制
  • 模版解析支持
  • 动态视图
  • 用户会话
  • CSRF 保护
  • 静态文件服务
  • 错误控制器
  • 访问日志
  • 缓存
  • 插件支持

Express 工程的结构

|—— bin/
|
|—— node_modules/
|
|—— public/
| |
| |—— images/
| |—— javascripts/
| |—— stylesheets/
|
|—— routes/ 为指定路径组织返回内容,相当于 MVC 架构中的控制器
| |
| |—— index.js 路由文件,相当于控制器,用于组织展示的内容
|
|—— views/
| |
| |—— index.jade 模版文件,当前为 routes/index.js 中调用的模版
|
|—— app.js 工程的入口
|
|—— package.json

各文件说明

app.js

app 对象一般情况下都是指向 Express 应用,通过调用 Express 模块的 express() 方法创建

var express = require('express');
var app = express();

app 对象配有一些成员方法:

  • app.METHOD 和 app.param,用来处理路由 HTTP 请求
  • app.route,用来配置中间件
  • app.render,渲染 HTML 视图
  • app.engine,注册模版引擎

app.set 是 Express 的参数设置工具,接受一个 key 和一个 value
可用的参数有:

  • basepath:基础地址,通常用于 res.redirect() 跳转
  • views:视图文件的目录,存放模版文件
  • view engine:视图模版引擎
  • view cache:启用视图缓存
  • case sensitive route:路径区分大小写
  • strict routing:严格路径,启用后不会忽略路径末尾的“/”
  • jsonp callback:开启透明的 JSONP 支持
    app.set('title','My Site');

app.get 可以获取 setting 里 key 对应的 value
eg: app.get(‘/‘,routes.index); 是一个路由控制器,用户如果访问“/”路径,则由 routes.index 来控制

app.use 用来启用大量的中间件
(在 Express3.X 时依赖于 Connect)
(而在4.X开始,除了 Static 其余则被分离成独立的模块,需要单独安装,使用 require 调用)

var morgan = require('morgan'); //logger模块的这个新名字真是神奇
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());

在 hexo 新建一个不依赖模板配置的空白页面

发表于 2016-03-31

hexo 有两个新建文件的命令,一个是 hexo new +文件名;另一个是 hexo new page +路径名

通过第二种方式,我们可以在 source 里新建一个目录,不同一般的文章,而是有一个新的页面,供我们访问,如 localhost:4000/about

但通过这种方法生成的页面 index.md,也会在 hexo g 的时候,被默认套用了配置模板。

那有没有办法可以使这个页面不会依赖于模板呢?答案是有的。

在 index.md 文件头加上这么一句,就可以解决: “layout: false“

如:

---
layout: false
title: "this is a title"
date: 2016-03-31
---
<p>hello world</p>

这样就大功告成了。


Update On Sept 24th, 2016

然而并不是。
命令 hexo new page 只是新建一个页面。但它仍然是通过编译,将 md 文件编译成 html 文件。而属性 layout: false 的作用是,让 md 文件不套用网页模版。

真正要实现可以自己写静态网页放在博客上,要自己动手写 html、css、js 文件的话,就要利用 hexo 的配置属性:skip_render 。这个属性可以在编译时跳过某些目录,hexo 会直接把这个目录原封不动地放到 public/ 去。
P.s. 这个属性的文件匹配有多种形式:

  1. 某目录下全部文件 – skip_render: demo/*
  2. 某目录下全部的指定类型的文件 – skip_render: demo/*.html
  3. 某目录下全部文件及其子目录 – skip_render: demo/**
  4. 如果有多个目录需要设置为跳过编译的话:
    skip_render:
    - 'demo1/\*'
    - 'demo2/\*.html'
    - 'demo3/\*\*'

这样,就真的大功告成了~
看我个人博客的 Demo 页。

AngularJS 的数据绑定

发表于 2016-03-30

使用 AngularJS,最重要的特点之一,就是它的数据绑定了。

共性

在 AJS 中,经常需要将给定的变量或者表达式,来添加在某个 html 元素内,这个时候经常用到的就是 ng-bind 和双括号(hexo不允许使用半角的花括号,因此只能用中文或者是全角符号了)了,如:

<div ng-init="str='hello'">
<p ng-bind="str"></p>
<p>{{str}}</p>
</div>

在这个例子中,两个 p 元素都能在浏览器上显示 str 的内容。这也就是数据绑定的实现。

个性

尽管 ng-bind 和双括号的作用是一致的,但是两者仍然有一些区别。在两者之中,也更推荐使用 ng-bind。

可见性

所谓的“可见性”,就是指,在打开页面时,页面内会展现出 AJS 的变量或者表达式。
这是因为此时 HTML 内容已经加载完成,但 Angular 脚本尚未加载完成,因此还没有替换掉 HTML 中的双括号注释。
事实上这个也是我在刚开始学习开发 Angular App 时遇到的问题。
这个问题可以通过使用 ng-bind 来解决,这也是利用了 ng-bind 和双括号在可见性的区别。
使用双括号时,HTML 加载时,会将这个注释视为字符串,直接打印出来;而使用 ng-bind 的时候,因为 ng-bind 是作为 HTML 元素的属性,因此对于用户是不可见的,因此不会将变量或者表达式暴露出来。

// 使用 ng-bind
<div ng-bind="str"></div>
// 而不用 {{}}
<div>{{str}}</div>

p.s. 对于这个现象,还有另外一个解决方案,就是使用 ng-cloak,配合 css 的属性选择器,在 Angular 脚本加载完成前,将带有 ng-cloak 指令的节点隐藏掉,即:

[ng:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}

但是这个方法美中不足的在于,angular 加载完成之前,添加了这个指令的元素会处于空白状态,特别的,加在 body 时,会出现白屏状态。

性能

并不是只因为使用双括号会暴露表达式就推荐使用 ng-bind 的。更重要的是两者在性能方面上的差异。
事实上,使用双括号,速度相对较慢。(这里是指数据较多的情况,下同)
造成性能差异的原因是:
首先对于双括号来说,angular 会在每次 $digest 循环时对花括号内的变量进行检查,并且将变量的值重新输出到 HTML 中;
而对于 ng-bind 这个指令来说,它会被放置一个 watcher 监听器,只有当监听器监听到它绑定的变量的值发生变化时,ng-bind 才会应用,更新绑定变量的值

引用 stackoverflow 里一位叫 Konstantin Krass 的朋友的尝试:

I am currently building a big single page app (~500 bindings per view). Changing from {{}} to strict ng-bind did save us about 20% in every scope.$digest.

去掉 IE 浏览器在 input 下自带的叉号和小眼睛

发表于 2016-03-27

在 Edge 浏览器下,对于 input[type=”text”] 来说,当在输入框里输入内容时,输入框右边会出现一个“×”号,点击之后可以清除掉该 input 里的所有内容。这个按钮有时对用户来说是比较方便的。但有时,我们可能不需要这个按钮,或者是我们需要自己定制一个符合指定样式和功能的按钮,因此这时候就需要将浏览器自带的隐藏掉

// 这个样式只是针对 IE 浏览器下 type="text" 的 input
input[type="text"]::-ms-clear {
display: none
}
// 也可以指定所有 input
input::-ms-clear {
display: none
}

同样,有时候并不需要使用到 input[type=”password”] 的小眼睛(通过点击可以看到密码的内容),因此隐藏的方法如下:

// 这个样式只是针对 IE 浏览器下 type="text" 的 input
input[type="password"]::-ms-reveal {
display: none
}
1…678
Andre Huang

Andre Huang

40 日志
19 标签
GitHub
© 2018 Andre Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.3