代码改变世界

JavaScript学习笔记

2015-01-13 21:01  郭志通  阅读(193)  评论(0编辑  收藏  举报

基础知识

1、this是在函数运行时生成的一个内部对象:

  1. 只能在函数内部使用。
  2. 代表调用函数的那个对象。
  3. 在构造方法中调用时,指向新生成的对象。

2、由于JS不是面向对象,那么要做到模块化就需要用到一些技巧来实现下面这些目的:

  1. 不能污染全局变量。
  2. 不能暴露所有成员,而且模块内部的成员不能被外部的代码修改。

如果是只有一个小文件的话在一个文件中没什么问题,但是在大工程中模块的作用就非常重要了。在CommonJS中,有一个全局的require方法来完成模块的加载(在很多组件中能看到这种用法):

// 第一个参数为所需要的模块数组,第二个参数为回调函数。
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
	// 回调函数的代码。
});

3、在实现模块化的时候一般会用到立即执行函数,直观上来看应该叫匿名立即执行的函数,一般有两种写法:

(function () { /* code */ } ());
(function () { /* code */ })();

应该是在括号中的东西被当做是要用的参数,所以才会立即执行吧。

4、闭包

这里是阮一峰老师对闭包的定义:闭包就是能够读取其他函数内部变量的函数。能达到的效果就是让这些变量的值保存在内存中,来看一个例子:

	var obj = function () {
		var a = '';
		return {
			set: function (val) {
				a = val;
			},
			get: function () {
				return a;
			}
		}
	};
	var b = obj();
	b.set('new val');
	alert(b.get());// new val

按照正常的情况方法的东西都会在执行完成后被回收掉,但是由于set&get方法中保持了引用,所以此时并不会销毁。这里有另外一个专业解释:

闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。

各种理解之间有点差别。

 

其他

模块化

在JS定义的方法、变量都将作为全局变量,如果都这么搞的话大家做各种JS包之间的冲突将会非常严重,而且如果想将JS用在后端编程,模块化是必须的。简单地用立即执行函数定义模块如下:

var module1 = (function(){
	var _count = 0;
	var m1 = function(){ /* code */};
    var m2 = function(){ /* code */};
    return {
		m1 : m1,
		m2 : m2
	};
})();

模块化除了分离各个部分,还需要考虑如何防止其他人修改模块中的方法和属性,更多可以看这里。在使用模块上面有两个规范:CommonJSAMD,在CommonJS中有一个全局的require方法来加载模块:

var math = require('math');
math.add(2,3);

这样做最大的问题在于math.add需要在math模块加载完成之后才能执行,在浏览器端显然这是没办法接受的。AMD(Asynchronous Module Definition:异步模块定义)就是应对这种场景产生的,采用异步方式加载模块,模块的加载不影响后面语句的执行,而依赖于此模块的语句放在回调函数中以便模块加载完成之后执行:

require([module], callback);

其中module是要加载的模块,callback则是加载成功之后执行的回调函数。下面来看一个阮一峰老师的例子: 

// 在同级目录下新建main.js
define(function (){
	var add = function (x,y){
		return x+y;
	};
	return {
		add: add
	};
});
// 在页面上加载模块
require(['./math'], function (math){
	alert(math.add(1,1));
});

使用require.js的地址在这里。如果要定义的模块还依赖其他模块,那么define的第一个参数可以用来指定:

define(['myLib'], function(myLib){/* code */ }

另外可以用require.js来加载非规范的模块定义,可以看这里

PS:太多的JS都是用了模块化,看完了几篇文章有了一点大致的了解了(2015/1/23)。

jQuery

这是目前使用最广泛的一个JavaScript函数库,简化了很多前端开发,而且使得代码的可读性提高了一大截,下面来看简单的用法:

$(document) //选择整个文档对象
$('a:first') //选择网页中第一个a元素
$('div').has('p'); // 选择包含p元素的div元素
$('div').parent(); //选择div元素的父元素
$('div').find('h3').eq(2).html('Hello');// 链式操作
$('h1').html('Hello'); //html()有参数Hello,表示对h1进行赋值
$('div').insertAfter($('p'));// 插入元素
$('<li class="new">new list item</li>');// 创建元素
// 绑定事件
$('input').bind(
	'click change', //同时绑定click和change事件
	function() {
		alert('Hello');
	}
);

另外还可以实现一些特殊效果,这里有jQuery的API文档,虽然jQuery用起来很爽,但是对性能、资源的消耗较大,也要慎重使用(可以参考这里),既然用jQuery对性能有损耗,如果我们做一些简单的功能,那么是不需要用jQuery的,而且jQuery太大的,网络不好的时候有点头疼,解决办法是用一些JavaScript原生的方法来代替jQuery:

function request(type, url, opts, callback) {
	var xhr = new XMLHttpRequest();
	if (typeof opts === 'function') {
		callback = opts;
		opts = null;
	}
	xhr.open(type, url);
	var fd = new FormData();
	if (type === 'POST' && opts) {
		for (var key in opts) {
			fd.append(key, JSON.stringify(opts[key]));
		}
	}
	xhr.onload = function () {
		callback(JSON.parse(xhr.response));
	};
	xhr.send(opts ? fd : null);
}

这样简单地对原生的请求包装一下也能达到类似Ajax的效果(更多可以看这里),另外还有很多jQuery的替代方法,比如zepto.js

PS:很多工具用起来都会有副作用,要多思考利弊(2015/1/25)。

 

 

 

 

 

 

 

 

 

 

------ update ------