JS模块化编程与AMD

常规代码

写JS代码时,我们根据自己的逻辑写出很长的代码后,往往一段时间后,如果重新去看自己写的代码时,会发现根本就不知道我写的是什么,以移动端画板为例,大约200行代码自上而下堆在在JS文件里,通篇的都是for循环和if else条件判断。这是典型’意大利面’式代码,由于过多使用if else跳转指令,显得代码结构异常混乱。
如果代码写成这样,我相信无论是谁都不会有兴趣去阅读你的代码,更严重地是在以后团队项目里,你无法跟别人合作,别人根本就不知道你写的什么,遇到一个bug时,得把所有的逻辑过一遍,然后才能测试代码。

分模块

为了解决这种代码结构混乱的情况,我们可以分模块来写。所谓一个模块就是划分一个独立的单元,让其功能独立,除了一些必需的全局变量,你不在依赖其它变量。每一个模块里的代码,为了更方便开发者阅读,你可以把代码里的一个一个小功能封装成函数。让你的主干内容一目了然。以移动端画板优化后的代码来看,与前面的来比,明显结构更加清晰。这就是按模块写代码的好处。

立即执行函数

以下面代码为例:

Read More

浅谈Promise对象

  1. 概念

    Promise对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单来说是用来处理异步请求。
    window.Promise是JS的一个内置对象。

    回调时代

    在以前处理异步的代码时,都是用的回调函数。以下面代码为例:
    假如当点击一个按钮时,发起一个AJAX请求,click函数接受两个回调函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    button.onclick = function(){
    click('GET','/xxx.js',function(xxx){
    console.log(xxx)
    },function(yyy){
    alert(yyy)
    })
    }
    function click(method,url,successCallback,errorCallback){
    $.ajax({
    type: method,
    url: url,
    success: function(responseText){
    successCallback(responseText)
    },
    error: function(xhr){
    errorCallback('请求错误,错误码为'+xhr.status)
    })

    Read More

立即执行函数

概念

什么是立即执行函数,顾名思义在声明一个函数之后,立马执行它。这个函数一般是匿名函数。

作用

立即执行函数的实质就是想创建一个独立的作用域,这个作用域里的变量,外面访问不到。

1
2
3
4
5
function xxx(){
var a=1
console.log(a)
}
xxx()

如果把这个变量放到函数里,不就行了吗?但这样存在的问题是,虽然你隐藏了一个变量,但你又暴露了一个全局变量xxx
其实,我们只要把这个函数变成匿名函数就行了。

1
2
3
4
function (){
var a=1
console.log(a)
}.call()

Read More

JS:什么是闭包

概念

闭包在JS中,实际上是不存在的,它只是一种马后炮式的总结。在自己写代码时,根本就不知道闭包,只是按照自己的思维来写的,最后,发现了某段代码符合闭包的定义。
如果一个函数用到了它外面的变量,那么这种做法就是闭包。

举例分析

比如我们在做一个游戏,某一个角色有30条命,在写还剩多少条命的代码时,可以用一个全局变量表示:

1
var lives = 30

在减少一条命后,把lives减去1即可,但这样做并不妥,任何人都可以改变这个全局变量的值,所以我们得让外面不能直接访问这个变量,得按我们自己规定的方法才能访问,不难想到可以用局部变量。只要我们在某个函数里声明这个变量,这个变量就是局部变量了。但是局部变量别人访问不到,你可以暴露一个函数,让别人可以间接访问。代码如下:

Read More

JS:异步与回调函数

同步与异步

JS语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

同步模式

同步模式是指后一个任务等待前一个任务的结束,才开始执行。程序的执行顺序与任务的排列顺序是一致的,同步的。以<script src="xxx.js"></script>为例,它就是同步执行的,在浏览器解析到这句代码时,就会停止下一行的解析,去下载要请求的JS文件,并执行它,然后再开始解析下一步代码。

Read More

跨域请求

同源策略

浏览器基于用户隐私考虑,禁止不同源的网站之间相互调用AJAX,对于页面加载不同源的CSS样式表、图像和脚本等资源是可以进行跨域请求。这里说的同源策略是仅指浏览器而规定,用命令行的话并不存在同源策略。
所谓同源是指同协议、同域名和同端口。例如http://xxx.comhttp://xxx.com就属于同源,后面接的路径可以不同。
这里说的禁止AJAX的跨域请求,并不是说浏览器不会向服务器发起请求,而是服务器不会把响应内容给浏览器。

CORS

CORS是一个W3C标准,全称为‘跨域资源共享’(Cross-origin resource sharing),实质就是跨域Http请求,它允许浏览器向跨域服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源之间发请求。

Read More

JS:new

前提

本文不从面向对象的角度来讨论new命令,而是以’省代码’的角度来看new。

模拟造士兵

如果我们要造一堆士兵,每个士兵有生命值、编号、攻击力和攻击行为。这些特性在计算机里就是一堆属性,有些属性是士兵私有的(生命值和编号),有些属性是每个士兵都共有的(攻击力和攻击行为)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var container = []
var soldier
soldier.prototype = {
attackValue: 10,
attack: function(){/*攻击行为*/}
}
for(var i =0 ; i<100 ; i++){
soldier = {
id: i,
HP: 100
}
}
//_proto_不是标准属性,实际中不能这么写
soldier._proto_ = soldier.prototype
container.push(soldier)

Read More

JS:原型链

原型链

原型

1
2
var arr = []
arr.push('1')

arr明明是个空数组,为什么会有push方法?在这个过程中,我们看看浏览器做了什么,在声明一个空数组时,浏览器会默认给arr绑定一个隐藏的属性,即arr._proto_。然后把早已开辟好的数组的原型Array.prototype指向这个隐藏的属性。即arr._proto_ = Array.prototype将其赋值。而数组的原型有push方法,当写arr.push()时,会查找arr自身是否有push属性,如果没有就会到arr._proto_里去找,显然arr._proto_.push是存在的。一般情况下,可以省去_proto_,直接写成arr.push,浏览器默认会到原型里去找。
如果在Array.prototype里没找到,则会到下一层原型里去找。如果要调用arr.toString(),数组的原型Array.prototype._proto_指向对象的原型Object.prototype。对象的原型最终指向Null。

Read More

This

this的重要性

this是JavaScript中最为关键的语法点,一般在简单项目里,this可有可无,但大部分的开发任务中,this起着关键作用。

this的由来

以下面JS代码为例,调用该自身对象的其它属性的值。

1
2
3
4
5
6
7
var obj = { 
name: 'allen',
say: function(){
console.log('你好,'+obj.name)
}
}
obj.say() // 'allen'

Read More

从URL输入到页面展示

全局概念

URI名叫统一资源定位符,用于定位互联网上的资源。URL是URI的一种,一般在操作页面用URL。

  1. 用户请求远程资源

  2. 浏览器查找远程资源,打包用户请求并发送。

  3. 服务器根据用户请求的资源路径及附加参数,配合自身逻辑生成相关内容,发送到浏览器。、

  4. 浏览器解析结果,呈现直观的方式。

    Read More