js中的class

在js中,类(class)是ECMAScript 6新引入的一个语法糖,仍然基于js中已经存在的基于原型的继承模型,因此,这个语法并没有为js引入新的继承模型。事实上,class仍然是特殊的函数。

类定义:

定义类的方式和定义函数的方式一样,也有两种,分别是类声明以及类表达式

1 类声明:

1
2
3
4
5
6
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}

类声明与函数声明的一个显著区别是,在函数声明中,存在着变量提升的特性,而在类声明中,则没有这个特性,因此,使用类声明的时候,一定要遵循先声明,后使用的原则。如下的代码就会报错

1
2
var p = new Polygon(); // ReferenceError
class Polygon {}

而下面这种代码则不会报错

1
2
3
var p = new Polygon();
function Polygo(){
}

2 类表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 匿名类 
var Polygon = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// 命名类
var Polygon = class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
};

android开发学习系列1

1. Android APP 基础知识

App Components(app组件)

app组件是一个android应用中最基本的构成块,每一个组件可以构成一个独立的app访问入口,但并不意味着每一个组件一定要成为app的一个访问入口。一共有四种组件:Activities,Services,Content Provider,Broadcast receivers

Activities(活动)

一个Activity(活动)代表了独立的,具有用户界面的一屏区域。

Services(服务)

一个服务是一个运行于后台,进行耗时长的操作或者是为远程进程处理任务的组件,服务不提供用户界面

Content Provider(内容提供商)

一个内容提供商管理着一份应用数据。其他应用可以通过内容提供商来查询甚至修改(前提是获得本引用的允许)本应用的数据

Broadcast receivers(广播接收者)

一个广播接收者是一个回应系统范围内的广播通知的组件,很多广播就来源于系统。比如通知屏幕关闭,电量低等。应用也可以发起广播,比如:让其他应用知道一些数据已经被下载到设备上了,可以供这些应用使用了。尽管广播接收者不显示用户界面,它们却有可能在广播事件发生的时候通过创建状态栏通知来告知用户。

Android系统设计的一个独特点在于任何一个app都可以启动另一个app的组件。所以
Android app没有一个单点入口。
而由于每个app都通过文件权限限制访问其他应用,并且系统将每个应用都运行在独立的进程中,所以我们并不能直接激活另一个app中的组件,但是Android系统是可以做这件事情的。所以如果要激活另一个app中的组件,就必须向系统发送消息以指明启动特定app组件的意图。然后系统才会为我们激活要求的组件。

Activating Components(激活的组件)

以上四种组件中的三种-Activities(活动),services(服务),broadcast receivers(广播接收者)-都是通过一个叫做intent(意图)的异步信息激活。不论组件是属于你的app还是别人的,intent都是在运行时将互相独立的组件绑定到一起。

npm install -g package_name 权限问题应对方案

当我们在普通用户组条件下使用命令npm install -g package_name时候,可能会碰到如下错误提示:

1
2
3
4
5
6
7
8
9
10
$ npm install -g npm
Error: EACCES: permission denied, access '/**/**/**/node_modules/npm/node_modules/cmd-shim/node_modules/graceful-fs'
npm ERR! at Error (native)
npm ERR! { [Error: EACCES: permission denied, access '/**/**/**/node_modules/npm/node_modules/cmd-shim/node_modules/graceful-fs']
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'access',
npm ERR! path: '/**/**/**/node_modules/npm/node_modules/cmd-shim/node_modules/graceful-fs' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

这是因为普通用户对于npm默认使用的文件夹不具有足够的权限。
根据官方文档说明
有两种解决办法:

  1. 修改默认全局npm包安装位置内文件夹的权限
  2. 使用另外一个文件夹作为全局npm包安装位置

方案一

步骤1 察看对全局npm包安装位置的设定

1
$ npm config get prefix

特别注意:官方文档明确指出,如果npm config get prefix命令返回值为/usr,则必须使用第二种方案

步骤二 更改必要目录的权限

1
$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

这条命令目的是将全局安装npm包的路径下的lib/node_modules,/lib/bin,lib/share目录的拥有者设置为当前普通用户。因为这些目录的拥有着本身就具有对这些目录的读写权限,所以问题得以解决(此方案我执行过多次,没有碰到问题)
然后再次运行之前运行不通过的命令,现在可以顺利通过了

方案二

步骤一 在合适位置创建一个文件夹

1
$ mkdir ~/.npm-global

步骤二 使用之前创建的文件夹作为全局npm包安装的位置

1
$ npm config set prefix '~/.npm-global'

步骤三 将新设定的路径加入环境变量

1
$ export PATH=~/.npm-global/bin:$PATH

将我们设定的全局npm包安装位置下的bin目录加入到系统环境变量,这样我们才可以在任意命令行位置都能执行全局npm包提供的命令

步骤四 让系统重新载入环境变量

1
$ source ~/.profile

完成之后,再次运行之前运行不通过的命令,现在可以顺利通过了

javascript之每天一个模式系列(1)

每天一个设计模式之单例模式

在单例模式下,仅需要创建一个对象,并且不需要在使用的时候实例化这个对象。也就是说,在全局范围内,任何时候访问的都是同一个对象里面的资源。
一个普通的单例模式:

javascript单例模式
1
2
3
4
5
6
7
8
9
var singleton = {
param : 1,
method : function(){
alert( this.param );
}
}
singleton.method();
singleton.param = 2;
singleton.method();

在javascript中,单例模式特别适合于创建命名空间

javascript命名空间
1
2
3
4
5
6
7
8
9
10
var Namespace = {
Util : {
utilMethod1 : function(){},
utilMethod2 : function(){}
},
Ajax : {
ajaxMethod1 : function(){},
ajaxMethod2 : function(){}
}
}

通过上面的方式,我们可以控制一个页面只有有限甚至一个全局变量暴露在外,从而避免出现全局变量污染问题。

javascript之我掉过的那些坑

JSON.parse()方法

在使用原生JSON.parse()方法解析json形式的字符串的时候,例如:

call方法演示
1
2
var str = '{"key":"value"}';
JSON.parse( str );

可以返回期望的json对象,但是如果改写上述代码为
call方法演示
1
2
var str = "{'key':'value'}";
JSON.parse( str );

则会报错,也就是说使用JSON.parse()方法需要被解析的json形式字符串要严格使用双引号分别包裹键和值

javascript 中处理货币问题

在使用javascript处理货币运算(主要是加减乘运算)的时候,会碰到对浮点数的运算(整数运算是没有问题的),然后某些情况就会出现算术上的差异,这主要是因为计算机是以二进制方式处理数据,对于某些十进制的运算不能得到精确值,比如:

货币处理方法演示1
1
2
3
4
var price = 56.06;
console.log( price*11 );

console.log( price - 0.01 );

以上两种情况都会输出一长串结果,并不符合我们的预期。
针对上述情况,有一种解决方案:
方案一:对计算结果进行四舍五入运算,具体做法是使用Math.round()函数,因为这个函数返回最接近的整数,所以要先把原数据扩大100倍,再对舍入的结果缩小100倍
方案二:从一开始就对所有计算中的数据扩大100倍,使之变为整数运算,之后再对计算的最终结果缩小100倍,得到正确的结果(此处又掉坑,比如8.55*100就得不到855)

货币处理方法演示2
1
2
3
4
5
6
7
8
9
10
// 方案一:
var price = 56.06;
console.log( Math.round( ( price*11 )*100 )/100 );

// 方案二:
/*
var price = 56.06;
var intPrice = price*100;
console.log( ( intPrice*11 )/100 );
*/

gulp learning (2)

在上文中讲解了gulp的常规安装,本文继续讨论gulp的使用

在gulp中,流是个非常重要的概念,请看下面的一段代码

1
2
3
4
5
6
7
8
var gulp = require( 'gulp' ),
uglify = require( 'gulp-uglify' );

gulp.task( 'uglify', function(){
gulp.src( "demo.css" )
.pipe( uglify() )
.pipe( gulp.dest('demo.min.css' ) );
});

这里uglify任务中首先读取了demo.css文件,然后使用gulp-uglify模块提供的uglify方法进行压缩,最后导出为demo.min.css文件,中间所有步骤都没有产生中间文件,而是使用数据流,也就是说上一个操作的输出被下一个操作作为输入进行处理,依次进行,直到最后一次处理后才输出文件。

browserify

如果要在浏览器项目中使用符合commonJS规范的javascript模块,需要使用browserify。通过使用browserify,我们既可以定义符合commonJS规范的javascript模块在客户端使用,也可以直接引用nodejs模块用于浏览器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var gulp = require( 'gulp' ),
transform = require('vinyl-transform'),
browserify = require( 'browserify' );

gulp.task( 'browserify' , function() {

var browserified = transform(function(filename) {
var b = browserify(filename);
return b.bundle();
});
gulp.src( './js/*.js' )
.pipe( browserified )
.pipe( gulp.dest( './dist/js' ) );

});

上述代码就是将js文件夹下的所有commonJS规范的模块都分别通过browserified转换为浏览器可以执行的javascript代码,而其中普通形式的javascript代码则不做转换,最后都输出到dist文件夹下的js文件夹里

uglify

使用uglify对javascript文件进行压缩,使用方式如下面代码所示:

1
2
3
4
5
6
7
8
var gulp = require( 'gulp' ),
uglify = require( 'gulp-uglify' );

gulp.task( 'default', function(){
gulp.src( './js/*.js' )
.pipe( uglify() )
.pipe( gulp.dest( './dist/js' ) );
});

rev

gulp-rev

gulp learning (1)

gulp 是继grunt之后的又一个前端集成解决方案,以任务为核心概念,具有简单易学的特点。在linux命令行下的安装方式如下

全局安装

gulp依赖nodejs,如果没有安装nodejs,需要首先安装nodejs,在此不多叙述。请移步官方网站获取安装指导
全局安装gulp

1
npm install --global gulp

安装gulp为项目依赖

1
npm install --save-dev gulp

在项目根目录下创建gulpfile.js文件

1
2
3
4
5
var gulp = require('gulp');

gulp.task('default', function() {
// place code for your default task here
});

运行gulp

1
gulp

这里就会运行gulp的默认任务,也就是gulpfile.js文件中定义的default任务

javascript 函数 (1)

call()方法

第一个实参是要调用对象的母对象,比如f.call( obj ); 就是调用obj对象的f方法,第一个参数之后的所有实参就是要传入待调用的函数的值
比如:

call方法演示
1
2
3
4
5
function list() {
return Array.prototype.slice.call( arguments); //这里就是调用arguments对象的slice方法
}

var list1 = list(1, 2, 3); // [1, 2, 3]

apply()方法

同call()方法,不同之处是call方法接受逗号分割的参数,而apply接受一个数组或者是类数组对象,上面的例子使用apply方法改写则如下:

apply方法演示
1
2
3
4
5
function list() {
return Array.prototype.slice.call( arguments); //这里就是调用arguments对象的slice方法
}

var list1 = list( [ 1, 2, 3] ); // [1, 2, 3]