js是一门基于对象的弱类型语言,至于用处可谓是无处不在,GitHub语言排行榜稳稳的第一,JS终究一统世界…不来学习下?起码前半部分还是java呢!虽然和java并无啥关系
还有一个原因是,这几天微信小程序弄的沸沸扬扬,我也漫无目的的去学习了下,也涉及到了js,微信小程序已经内测,你的js知识储备准备好了么??o( ̄▽ ̄)ゞ)) ̄▽ ̄)o
写的比较混乱 = =!因为感冒嘛~
开始
js一般要和html、css配合起来用,所以还是要有一些html之类的知识的,嘛~不就是一堆标签吗?学习下也用不了多长时间,js的代码我们一般可以写在两个地方:
- html文件中
<script type="text/javascript">这里写js代码</script>
可以放在页面的任何位置,但是我们一般放在网页的head或者body部分。
如果在head部分:浏览器解析head部分就会执行这个代码,然后才解析页面的其余部分。
如果在body部分:网页读取到该语句的时候就会执行,执行完后再读取下面的 - 外部js文件
写在单独的扩展名为.js的文件中然后在html中引用,js文件中不需要再加标签,引用方式:<script type="text/javascript" src="script.js"></script>
,注意的是标签中间不能再写js代码,如果需要补充代码的话可以再写一个标签。
一般来说,script 要放到 body 的最下面,提高加载速度,如果放到 head 里那就会影响 HTML 结构的渲染,理论上说放那都行,但是规范上 js 属于正文部分,所以最好是放在 body 里面。
但是呢,如果页面引用了多个文件,不能保证在用时已经加载完毕,所以很多选择性放在头部还是尾部。
http://sfau.lt/b5saPH
基础语法
很多地方其实还是和其他语言有很大相同点的,这里主要总结一些和其他不同的地方,因为也没学过什么解释型语言。
Js中有一种叫严格相等===
,也就是比较对象而不是数值
变量
js是弱类型语言,所以变量的类型不会像java那样细分,定义变量只有一个关键字 var使用就是:var 变量名
理论上名称是可以任意取名,同样最好遵守下命名规范:
1.变量必须使用字母、下划线(_)或者美元符($)开始。
2.然后可以使用任意多个英文字母、数字、下划线(_)或者美元符($)组成。
3.不能使用JavaScript关键词与JavaScript保留字。
更详细的在这:https://github.com/fex-team/styleguide/blob/master/javascript.md
注意:
变量也可以不声明,直接使用,但为了规范,需要先声明,后使用,不声明的话就会是(隐式)全局变量[定义全局变量的正统方式]
当变量没有初始化就被使用 就会显示undefined
js 中 false、null 就是0,非 0 就是true 是可以运算的如: false + 1 = 1 ; true + 1 = 2
或者说,null、0、undefined、’’(空字符串) 这些都是 false,可以(可能是部分浏览器)通过 if 判断
函数和属性
因为js中没有class(类)的概念,所以函数很重要!基本定义如下:
1 | //常规定义 |
以及一个简单的调用:<input type="button" value="点击我" onclick="funName()" />
注意:
js中的函数没有重载(函数其实就是一个对象,对象只有覆盖),所有的参数被函数内的arguments所接收,即使是空参的,所以说空参的函数你也可以向里传参数,同时也可以传部分参数,你没传的参数默认就是undefined了
js中函数就是对象,var x = show 不加括号的话相当于直接指向了那个对象,加括号相当于进行了运算,然后把运算后的值给x(和最近学的Py好像)
可以被封装起来用
JS中所有.
的调用都可以替换成['']
,他们是等价的,在拼接的时候只能用第二种方式,下面两句是等价的:
1 | obj.prop = "abc"; |
函数还可以封装起来当作java中的class来使用,涉及到定义属性,JavaScript中有三种不同类型的属性:命名数据属性,命名访问器属性以及内部属性,关于属性其实上面多少已经使用了一些,几个例子:
1 | function Test(name){ |
其实还可以定义一个空函数用来做构造器,构造函数首字母一般大写,用来区分
1 | function Class(){} |
这里首先声明下,js中的{}一般代表定义一个对象,大部分情况下是要有成对的属性或值,或函数
命名数据属性
这个是我们通常所用的“普通”属性,感觉挺像json的格式的
1 | var obj = { |
命名访问器属性
概括一下就是:借助函数来获取或设置一个属性的值
1 | var obj = { |
调用后的效果:
—>obj.prop
‘Getter’—>obj.prop = 123;
Setter: 123
内部属性
有一些属性仅仅是为规范所用的,称之为内部属性,因为它们无法通过JavaScript直接访问到,但是它们的确存在,并且影响着程序的表现.内部属性的名称比较特殊,它们都被两个中括号包围着.下面有两个例子:
- 内部属性
[[Prototype]]
指向了所属对象的原型.该属性的值可以通过Object.getPrototypeOf()
函数读取到.该属性的值只能在创建一个新对象的时候通过Object.create()
或者proto来设置 [1].
例如:Object.getPrototypeOf(this).methodName1();
可以看下面的对象原型标题 - 内部属性
[[Extensible]]
决定了是否能给所属对象添加新的属性.该属性的值可以通过Object.isExtensible()
读取到.还可以通过Object.preventExtensions()
将该属性的值设置为false.一旦设置为false,就无法再设置回true了.
关于匿名函数
在javascript语言里任何匿名函数都是属于window
对象。在定义匿名函数时候它会返回自己的内存地址,如果此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了,因为匿名函数也是在全局执行环境构造时候定义和赋值,所以匿名函数的this
指向也是window
对象。
这里为什么要单独说下匿名函数呢,因为它好玩啊!还可以这样玩:
1 | //自执行函数 |
with语句和for…in
with语句主要是为了调用对象的方法可以省略函数名
1
2
3
4
5
6function a(name){
this.name = name;
}
with(a){
name = "bbb"; //不用写a.name
}for…in 可以用来遍历对象。遍历出的是变量名(假设理解为key:values可以理解为key),如果取值直接用
.
获取值是不行的,没法进行字符串的连接,所以要用[]
的方式来解决
遍历数组得到的是角标,同样需要arr[x]取值
关于 for in 及循环来了解一下:
1 | var array = [0,1,2,3,4,5,6,7,8,9]; |
在 for-in 需要分析出 array 的每个属性,这个操作的性能开销很大,用在 key 已知的数组上是非常不划算的。所以尽量不要用 for-in,除非你不清楚要处理哪些属性,例如 JSON 对象这样的情况。
在第二种循环中,效率也不高,循环每执行一次,都要检查一次 array.length 的值,读属性要比读局部变量慢,尤其是当 array 里存放的都是 DOM 元素(像 array = document.getElementByClassName("class");
),因为每次读 array.length 都要扫描一遍页面上 class=”class” 的元素,速度更是慢得抓狂。
下面就介绍几种优化后的代码:
1 | var array = [0,1,2,3,4,5,6,7,8,9]; |
这样就避免了每次判断 length 的尴尬情况。
其他补充
- 关于回调
js中的回调相比java就简单太多了,不需要接口啥的,因为变量可以指向函数嘛~所以到时候直接”执行”那个变量就好了嘛… - js中的全局函数
escape( )、eval( )、isFinite( )、isNaN( )、parseFloat( )、parseInt( )、unescape( )等
更多关于函数的解释见:https://segmentfault.com/a/1190000000660786#articleHeader11
对象原型
js中很多内部对象是拥有prototype属性的,对于拥有prototype属性的对象可以在原型的基础上增加功能扩展。下面的例子可以很好的说明这个功能,我们在string对象的基础上增加去空格和转置的功能:
1 | //去除前后空格 |
DOM
DOM:document object model 文档对象模型,简单说:将文档和标签以及其他内容变成对象。
DOM分为三层模型
dom1: 将html文档封装为对象
dom2: 在leve 1基础上加入了新功能,比如解析名称空间。
dom3: 将XML文档封装成对象
对于dom1的封装,可以视为将html的标签的层级关系封装成了树形结构,称为DOM树,每一个节点(标签)都是一个对象,能更好的进行管理(比如创建、删除、修改),能够动态的改变html的结构。
MDN: 文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。
说白了DOM就是浏览器为JavaScript提供的一系列接口(通过window.documnet提供的),通过这些接口我们可以操作web页面(JS 无法直接修改页面结构)。 但DOM并不是编程语言,它是文档对象的模型,该模型是独立于编程语言的。
关于DHTML:
是多个技术的综合体,叫做动态的html
DHTML=HTML+CSS+JavaScript+DOM
补充:在DHTML基础上加了轻量级的与服务器交互的功能就成了AJAX,DHTML+XMLhttpRequest = AJAX,比如google的搜索词预测
关于解析
对于DOM解析方式
好处:可以对树中的节点进行任意操作,比如:增删改查。
弊端:这种解析需要将整个标记型文档加载进内存。意味着如果标记型文档的体积很大,较为浪费内存空间。
另一种解析方式:
SAX:是由一些组织定义的一种民间常用的解析方式,并不是w3c标准,而DOM是W3C的标准。
SAX解析的方式:基于事件驱动的解析。随加载,随解析(读取到一个标签的结束标记就进行解析)获取数据的速度很快,但是不能对标记进行增删改。
关于节点
比较常见的又三种DOM节点:
元素节点:上图中
<html>、<body>、<p>
等都是元素节点,即标签。文本节点:向用户展示的内容,如
<li>...</li>
中的JavaScript、DOM、CSS等文本。- 属性节点:元素属性,如
<a>
标签的链接属性href
节点名称(nodeName)
元素节点的 nodeName 与标签名相同
属性节点的 nodeName 是属性的名称
文本节点的 nodeName 永远是 #text
文档节点的 nodeName 永远是 #document
节点的类型(type):
标签型节点:1
属性节点:2
文本型节点:3
注释型节点:8
document:9 (它的范围就是浏览器中整个显示网页的区域)
获取节点的方式
获取的方法有多种,获取子节点、父节点、兄弟节点之类的….
注意:标签之间如果存在空行,有的浏览器会认为是一个空白的文本节点
获取元素
一般我们常用的就是三种:
1 | //通过ID进行获取,window可省略 |
第一种返回的就是一个对象,后面的两个返回的是一个对象的集合,可以理解为数组,因为id只能有一个,其他的就不确定了。
获取到对象后可以根据API中的html属性所对应的DHTML样式属性(style)或者标签属性的名来修改内容。
其他
事件冒泡
微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document
事件捕获
网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p
后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡。
以下属于DOM2级处理程序了,0级就是直接设置onclick属性,DOM0级事件只会在冒泡阶段加载!
addEventListener的第三个参数就是为冒泡和捕获准备的.
addEventListener有三个参数:
element.addEventListener(event, function, useCapture)
第一个参数是需要绑定的事件
第二个参数是触发事件后要执行的函数
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
对于事件代理来说,在事件捕获或者事件冒泡阶段处理并没有明显的优劣之分,但是由于事件冒泡的事件流模型被所有主流的浏览器兼容,从兼容性角度来说还是建议大家使用事件冒泡模型。
下面的方法被对象所调用
type属性用于获取事件类型
target属性用于获取事件目标
stopPropagation()方法 用于阻止事件冒泡
preventDefault() 方法 阻止事件的默认行为
event.KeyCode 可用来屏蔽按键
event.returnValue=false 可以将事件取消掉(常用于表单)
event.srcElement 获取事件源对象(那一个对象触发的)
BOM
用于操作浏览器的对象,BOM的核心就是window对象,window对象指当前的浏览器窗口。
利用window对象可以操作浏览器的相关设置,比如地址栏、屏幕的大小、操作系统、窗口的位置等等,这个貌似不太经常用,这里不说了,用到了查API或者google之
不过一般会用到一些事件,如窗体装载、卸载啦
加载事件(onload)
事件会在页面加载完成后,立即发生,同时执行被调用的程序。卸载事件(onunload)
当用户退出页面时(页面关闭、页面刷新等),触发onUnload事件,同时执行被调用的程序。
关闭窗口
window.close :关闭本窗口
[窗口对象].close :关闭指定窗口History 对象
可以获取用户曾经浏览过那些网页,以实现后退、前进的功能其他常用对象
location用于获取或设置窗体的URL,并且可以用于解析URL。
Navigator 对象包含有关浏览器的信息,通常用于检测浏览器与操作系统的版本。
screen对象用于获取用户的屏幕信息。
其他常用函数/事件/属性补充
函数/事件名/属性 | 作用 |
---|---|
alert(字符串或变量) | 警告提示框,调试频繁用 |
confirm(str); | 确认提示框,点击确定返回true,点击取消返回false |
elementNode.getAttribute(name) | 通过元素节点的属性名称获取属性的值 |
elementNode.setAttribute(name,value) | 增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值 |
Object.innerHTML | 用于获取或替换 HTML 元素的内容。 |
object.className | 获取或者设置元素的类名 |
element.onmouseover | 鼠标经过事件 |
element.onmouseout | 鼠标移开事件 |
element.onfocus | 聚焦事件 |
element.onblur | 失焦事件 |
element.onchange | 文本框内容改变 |
Math.ceil() | 向上取整 |
Math.floor() | 向下取整 |
Math.round() | 四舍五入 |
Math.random() | 生成0-1的随机数 |
setInterval(代码,交互时间) | 从载入页面后每隔指定的时间执行代码 |
clearInterval(id_of_setInterval) | 取消计时器(间隔执行的) |
setTimeout(代码,延迟时间) | 在载入后延迟指定时间后,去执行一次表达式,仅执行一次,时间单位为毫秒 |
clearTimeout(id_of_setTimeout) | 取消计时器(一次性的) |
console.log() | 打印日志,还有其他等级如debug,各个等级的颜色等会不同 |
console.group() | 日志分组,便于查看,配合console.groupend()使用,一个表示开始一个表示结束 |
console.dir(cmd) | 列出指定命令/对象的所以方法 |
event.srcElement | 获取当前事件源对象(固定写法,一般直接传this来替代) |
elementNode.parentNode | 获取父节点,父节点只有一个 |
elementNode.childNodes | 得到全部的子节点(firstChild得到第一个,lastChile得到最后一个) |
isNaN() | 判断是否为数字 |
判断一个数是不是小数:
1 | // 如果输入的不是数字 parse 返回 NaN |
parseInt 可以强转开头为数字的字符串,字符会被忽略:parseInt ('123avc1');
也是可以正常转换的,而使用 Number() 方法转换包含字母的字符串会报错(返回 NAN),但默认是这种转换。
最后
用到什么比较频繁的东西到时候再回来更新吧…嗯,缓慢更新
对DOM不理解的可以去谷狗下DOM事件流
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~