基础
JavaScript是Web编程语言,由浏览器来编译并运行,现在基本上所有的HTML页面都使用JavaScript。
JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。
为什么学习 JavaScript?
JavaScript web 开发人员必须学习的 3 门语言中的一门:
- HTML 定义了网页的内容
- CSS 描述了网页的布局
- JavaScript 网页的行为
存在形式
1. script代码块
<script>
alert(“警告”)
<script>
2. 文件中
<script type="text/javascript" src="commons.js"></script>
JavaScript代码的放置位置
- 1. head中
- 2. body中的最下面(推荐方式)
因为在现实中有这样或那样的问题,如 js文件统一放在一个远端服务器上,由于网络加载问题,放在head头部的话,客户端访问站点时会首先加载js文件,但网络问题会导致无法加载站点页面,就连静态的内容也是看不到,所以JS代码的放置位置很重要!
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="http://js.dbq168.com/js/commons.js"></script> </head> <body> <h1>Hello World!</h1> </body> </html>
变量
变量是存储信息的容器。
定义变量:
<script> var name = "dbq"; #关键字 var var_name = 'var_value'; alert(name); </script>
变量可以使用短名称(比如 x 和 y),也可以使用描述性更好的名称(比如 age, sum, totalvolume)。
- 变量必须以字母开头
- 变量也能以 $ 和 _ 符号开头(不推荐这么做)
- 变量名称对大小写敏感(y 和 Y 是不同的变量)
变量分为全局变量和局部变量:
- 全局变量, name = "DBQ";
- 局部变量, var name = "Daniel";
name = "DBQ"; //全局变量 function f1(){ var name = "Daniel"; //局部变量 }
注释
单行注释: //代码
多行注释: /* .... */
// var name = "dbq"; 单行注释 // alert(name); 多行注释 /* name = "DBQ"; //全局变量 function f1(){ var name = "Daniel"; //局部变量 } */
PS: JavaScript代码每行写完后,注意使用;来作为代码结尾
数据类型
字符串(String)、数字(Number)、布尔(Boolen)、数组(Array)、对象(Object)、空(Null)、未定义(Undefined)
1. 字符串, String
字符串可以是引号内的任意文本,可以不加区分的使用单引号或者双引号,和Python中
var name = 'Daniel'; var age = "Male"; var address = 'Beijing Fengtai ';
常用功能:
length, 长度
a = "tom" "tom" a.length 3
trim 移除空白,相当于python的strip()
a = " tom "; " tom " a " tom " a.trim() "tom"
trimLeft 移除左空白
a.trimLeft() "tom "
trimRight 移除右空白
a.trimRight() " tom"
charAt(n) 返回字符串中的第n个字符
var name = "daniel"; undefined name.charAt(3); "i" name.charAt(2); "n"
concat(value, ...) 拼接
name "daniel" var age = 18; name.concat(age) "daniel18"
indexOf(substring,start) 子序列位置
name.indexOf("a")
1
lastIndexOf(substring,start) 子序列位置
var name = "daniel"; undefined name.lastIndexOf("an",1) 1
substring(
from
, to) 根据索引获取子序列
name "daniel" name.substring(1,5) //类似于python的切片,顾首不顾尾 "anie" name.substring(1,2) "a" name.substring(1,3)
slice
(start, end) 切片
name "daniel" name.slice(1,3) "an" name.slice(1,name.lenght) "aniel"
toLowerCase() 小写
name "DANIEL" name.toLocaleLowerCase() "daniel"
toUpperCase() 大写
var name = "tom"; undefined name.toUpperCase() "TOM"
split(delimiter, limit) 分割
var s1 = "I name is daniel"; undefined s1 "I name is daniel" s1.split() ["I name is daniel"] //分割后变成一个数组,也就是Python中的列表
search(regexp) 从头开始匹配,返回匹配成功的第一个位置(g无效)
s1 "I name is daniel" s1.search("I") 0 s1.search("d") 10
match(regexp) 全局搜索,如果正则中有g表示找到全部,否则只找到第一个。
s1.match("a"); ["a"] s1.match("a.*"); ["ame is daniel"] s1.match("a.+"); ["ame is daniel"]
replace(regexp, replacement) 替换,正则中有g则替换所有,否则只替换第一个匹配项:
- $数字:匹配的第n个组内容;
- $&:当前匹配的内容;
- $`:位于匹配子串左侧的文本;
- $':位于匹配子串右侧的文本
- $$:直接量$符号
s1.replace("sha","hehe"); "wosye bushsfdfjwoi shuod w sshi hehe,afnzneg shiuoel zhenme duo32" var s1 = "wosye bushsfdfjwoi shuod w sshi sha,afnzneg shiuoel zhenme duo32"; undefined s1.replace("sha","hehe"); "wosye bushsfdfjwoi shuod w sshi hehe,afnzneg shiuoel zhenme duo32" s1 "wosye bushsfdfjwoi shuod w sshi sha,afnzneg shiuoel zhenme duo32"
2. 数字, Number
JavaScript中的数字只有一种,浮点数和整数都叫做Number
var age = 18; var num = 3.1415926;
也可以使用科学计数法来标示:
var nums =123e5; // 12300000
转换
- parseInt(..) 将某值转换成数字,不成功则NaN
- parseFloat(..) 将某值转换成浮点数,不成功则NaN
特殊值:
- NaN,非数字。可使用 isNaN(num) 来判断。
- Infinity,无穷大。可使用 isFinite(num) 来判断。
var n1 = 18.332; undefined parseInt(n1); 18
var n2 = 18; undefined var res = parseFloat(n2); undefined res 18
res 18 isNaN(res) false n = "w" "w" isNaN(n); true
n1 18.332 isFinite(n1); true n3 = 12309394903990390190230; 1.230939490399039e+22 isFinite(n3) true n4 = 3; 3 isFinite(n4); true //无穷大是一个相对值,其实我也不知道到底多少才是无穷大...
更多数值计算:
常量
Math.E
常量e,自然对数的底数。
Math.E
2.718281828459045
Math.LN10
10的自然对数。
Math.LN10
2.302585092994046
Math.LN2
2的自然对数。
Math.LN2
0.6931471805599453
Math.LOG10E
以10为底的e的对数。
Math.LOG10E
0.4342944819032518
Math.LOG2E
以2为底的e的对数。
Math.LOG10E
0.4342944819032518
Math.PI
常量figs/U03C0.gif。
Math.PI;
3.141592653589793
Math.SQRT1_2
2的平方根除以1。
Math.SQRT1_2;
0.7071067811865476
Math.SQRT2
2的平方根。
Math.SQRT2
1.4142135623730951
静态函数
Math.abs( )
计算绝对值。
n1 18.332 Math.abs(n1) 18.332
Math.acos( )
计算反余弦值。
Math.asin( )
计算反正弦值。
Math.atan( )
计算反正切值。
Math.atan2( )
计算从X轴到一个点的角度。
Math.ceil( )
对一个数上舍入。
Math.cos( )
计算余弦值。
Math.exp( )
计算e的指数。
Math.floor( )
对一个数下舍人。
Math.log( )
计算自然对数。
Math.max( )
返回两个数中较大的一个。
Math.min( )
返回两个数中较小的一个。
Math.pow( )
计算xy。
Math.random( )
计算一个随机数。
Math.round( )
舍入为最接近的整数。
Math.sin( )
计算正弦值。
Math.sqrt( )
计算平方根。
Math.tan( )
计算正切值。
3. 布尔, boolen
布尔值只有两个值,true和false,常用于条件测试
var x = true; var y = false;
- == 比较值相等
- != 不等于
- === 比较值和类型相等
- !=== 不等于
- || 或
- && 且
var a = 3; undefined var b = "3"; undefined a == b; //卧槽,为啥能相等呢?。。。。 true a === b; false typeof(a); //类型不同,居然能相同,尼玛 "number" typeof(b); //所以要切记,==只对比值不对比类型 "string"
a != b; false a 3 b "3"
a === b; false a 3 b "3" //所以,对比值和属性,要用===
var a = 3; undefined var b = 4 undefined var c = 3; undefined var d = 2 undefined a > b || c < d; false a < b || c > d; true
var a = 3; undefined var b = 4 undefined var c = 3; undefined var d = 2 undefined a < b && c > d; true a < b && c < d; false
4. 数组
Java、C#中都有数组的概念,就连Shell中也有数组array(), 作用也就是相当于Python中的列表
var girls=new Array(); //现获取对象,new 是关键字 undefined girls[0]="Adele"; "Adele" girls[1]="Selina"; "Selina" girls[2]="Eda"; "Eda" girls ["Adele", "Selina", "Eda"]
或者 (condensed array):
girls_new = Array("Adele","Selina","Eda") ["Adele", "Selina", "Eda"] girls_new ["Adele", "Selina", "Eda"]
数组下标是基于零的,所以第一个项目是 [0],第二个是 [1],以此类推。
girls[0]; "Adele" girls[1]; "Selina" girls[2]; "Eda"
常用功能:
length 数组的大小
girls.length //类似于Python列表长度 3
push(ele) 尾部追加元素
girls.push("Elina"); 4 girls ["Adele", "Selina", "Eda", "Elina"]
pop() 尾部获取一个元素
girls.pop() "Elina" girls ["Adele", "Selina", "Eda"]
unshift(ele) 头部插入元素
girls.unshift('Helen'); 4 girls ["Helen", "Adele", "Selina", "Eda"]
shift() 头部移除元素
girls.shift() "Helen" girls ["Adele", "Selina", "Eda"]
splice(start, deleteCount, value, ...) 插入、删除或替换数组的元素
- obj.splice(n,0,val) 指定位置插入元素
- obj.splice(n,1,val) 指定位置替换元素
- obj.splice(n,1) 指定位置删除元素
girls ["Adele", "Selina", "Eda"] girls.splice(1,0,'Barbara'); [] girls ["Adele", "Barbara", "Selina", "Eda"] 在指定start位置插入value
girls ["Adele", "Barbara", "Selina", "Eda"] girls.splice(1,1,'Bea'); ["Barbara"] girls ["Adele", "Bea", "Selina", "Eda"] //替换制定位置的值为value
girls ["Adele", "Bea", "Selina", "Eda"] girls.splice(1,1); ["Bea"] girls ["Adele", "Selina", "Eda"]
slice
( ) 切片
girls ["Adele", "Selina", "Eda"] girls.slice(1,3); ["Selina", "Eda"] girls.slice(1); ["Selina", "Eda"] girls.slice(0); ["Adele", "Selina", "Eda"]
reverse( ) 反转
girls ["Adele", "Selina", "Eda"] girls.reverse() ["Eda", "Selina", "Adele"]
join(sep) 将数组元素连接起来以构建一个字符串
girls ["Eda", "Selina", "Adele"] s1 = 'hehe'; "hehe" girls.join(s1); "EdaheheSelinaheheAdele"
concat(val,..) 扩展数组
var boy = Array("Tom","Jerry","Sam"); undefined girls ["Eda", "Selina", "Adele"] girls.concat(boy); ["Eda", "Selina", "Adele", "Tom", "Jerry", "Sam"]
sort( ) 对数组元素进行排序
girls.sort()
["Adele", "Eda", "Selina"]
5. 对象
对象由花括号分隔,在括号内部,属性以key:value来定义,由逗号分隔,和Python中的字典一样。
var obj = {id:1, name:"tom", age:3}; undefined
访问属性:
obj.id 1 obj.name "tom" obj["id"] 1 obj["age"] 3 obj.age
6. Undefined 和 Null
Undefined 这个值表示变量不含有值,变量未定义。
可以通过将变量的值设置为 null 来清空变量,null是JavaScript中的一个特殊值,经常用来描述“空值”。
var name = "Daniel" undefined name "Daniel" var name = null; undefined name "null"
其他
1. 序列化
- JSON.stringify(obj) 序列化
- JSON.parse(str) 反序列化
var obj = {id:1, name:"tom", age:3}; //定义一个对象 undefined typeof(obj) //类型是object "object" obj.id //可以访问属性 1 re1 = JSON.stringify(obj) //序列化为字符串 "{"id":1,"name":"tom","age":3}" typeof(re1) "string" re1 "{"id":1,"name":"tom","age":3}" re1.id //字符串没有对象的属性的! undefined //反序列化回来 re2 = JSON.parse(re1) Object {id: 1, name: "tom", age: 3} re2 Object {id: 1, name: "tom", age: 3} typeof(re2) "object" re2.id 1
2. 转义
- decodeURI( ) URl中未转义的字符
- decodeURIComponent( ) URI组件中的未转义字符
- encodeURI( ) URI中的转义字符
- encodeURIComponent( ) 转义URI组件中的字符
- escape( ) 对字符串转义
- unescape( ) 给转义字符串解码
- URIError 由URl的编码和解码方法抛出
在Google里搜索关键字“林丹李宗伟里约”:
url="https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=%E6%9E%97%E4%B8%B9%E6%9D%8E%E5%AE%97%E4%BC%9F%E9%87%8C%E7%BA%A6"; "https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=%E6%9E%97%E4%B8%B9%E6%9D%8E%E5%AE%97%E4%BC%9F%E9%87%8C%E7%BA%A6" decodeURI(url) "https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"
decodeURIComponent(url)
"https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"
url2 = "https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"; "https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约" encodeURI(url2) "https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=%E6%9E%97%E4%B8%B9%E6%9D%8E%E5%AE%97%E4%BC%9F%E9%87%8C%E7%BA%A6"
encodeURIComponent(url2);
"https%3A%2F%2Fwww.google.com.hk%2F%3Fgws_rd%3Dssl%23newwindow%3D1%26safe%3Dstrict%26q%3D%E6%9E%97%E4%B8%B9%E6%9D%8E%E5%AE%97%E4%BC%9F%E9%87%8C%E7%BA%A6"
scape(url2)
"https%3A//www.google.com.hk/%3Fgws_rd%3Dssl%23newwindow%3D1%26safe%3Dstrict%26q%3D%u6797%u4E39%u674E%u5B97%u4F1F%u91CC%u7EA6"
unescape(url2)
"https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"
URIError(url2) URIError: https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约(…) URIError(url); URIError: https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=%E6%9E%97%E4%B8%B9%E6%9D%8E%E5%AE%97%E4%BC%9F%E9%87%8C%E7%BA%A6(…)
3. eval
JavaScript中的eval是Python中eval和exec的合集,既可以编译代码也可以获取返回值。
eval()
var a="1+2+3" undefined a "1+2+3" eval(a) 6
var b = "a+d+c" undefined eval(b) VM414:1 Uncaught ReferenceError: d is not defined(…)(anonymous function) @ VM414:1(anonymous function) @ VM413:1 EvalError(b) EvalError: a+d+c(…)
4、正则表达式
JavaScript中支持正则表达式,其主要提供了两个功能:
- test(string) 用于检测正则是否匹配
- exec(string) 用于获取正则匹配的内容
注:定义正则表达式时,“g”、“i”、“m”分别表示全局匹配,忽略大小写、多行匹配。
5、时间处理
JavaScript中提供了时间相关的操作,时间操作中分为两种时间:
- 时间统一时间
- 本地时间(东8区)
Date 对象用于处理日期和时间。
Date 对象属性
属性 | 描述 |
---|---|
constructor | 返回对创建此对象的 Date 函数的引用。 |
prototype | 使您有能力向对象添加属性和方法。 |
var time = new Date undefined
time
Sat Aug 20 2016 13:31:28 GMT+0800 (中国标准时间)
getTime()返回时间戳
time.getTime()
1471671566147
getFullYear() 返回当前年份
time.getFullYear()
2016
getMonth() 返回月份,但是是0-11月份,所以,需要+1才是当前月份
var time = new Date undefined time.getMonth() 7 time Sat Aug 20 2016 13:45:50 GMT+0800 (中国标准时间)
getDay() 以数字形式显示当前星期
time.getDay()
6
操作日期:
time.setFullYear(2018,3,1) //设定一个特定的日期2018年3月1日 1522561646583
<html> <head> <script type="text/javascript"> function startTime() { var today=new Date(); var Y = today.getFullYear(); var M = today.getMonth()+1; var D = today.getDate(); var h=today.getHours(); var m=today.getMinutes(); var s=today.getSeconds(); m=checkTime(m); s=checkTime(s); document.getElementById('txt').innerHTML=Y+ "-"+M+"-"+D+" "+h+":"+m+":"+s; t=setTimeout('startTime()',500) } function checkTime(i) { if (i<10) {i="0" + i} return i } </script> </head> <body onload="startTime()"> <div id="txt"></div> </body> </html>
方法 | 描述 |
---|---|
Date() | 返回当日的日期和时间。 |
getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31)。 |
getDay() | 从 Date 对象返回一周中的某一天 (0 ~ 6)。 |
getMonth() | 从 Date 对象返回月份 (0 ~ 11)。 |
getFullYear() | 从 Date 对象以四位数字返回年份。 |
getYear() | 请使用 getFullYear() 方法代替。 |
getHours() | 返回 Date 对象的小时 (0 ~ 23)。 |
getMinutes() | 返回 Date 对象的分钟 (0 ~ 59)。 |
getSeconds() | 返回 Date 对象的秒数 (0 ~ 59)。 |
getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999)。 |
getTime() | 返回 1970 年 1 月 1 日至今的毫秒数。 |
getTimezoneOffset() | 返回本地时间与格林威治标准时间 (GMT) 的分钟差。 |
getUTCDate() | 根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。 |
getUTCDay() | 根据世界时从 Date 对象返回周中的一天 (0 ~ 6)。 |
getUTCMonth() | 根据世界时从 Date 对象返回月份 (0 ~ 11)。 |
getUTCFullYear() | 根据世界时从 Date 对象返回四位数的年份。 |
getUTCHours() | 根据世界时返回 Date 对象的小时 (0 ~ 23)。 |
getUTCMinutes() | 根据世界时返回 Date 对象的分钟 (0 ~ 59)。 |
getUTCSeconds() | 根据世界时返回 Date 对象的秒钟 (0 ~ 59)。 |
getUTCMilliseconds() | 根据世界时返回 Date 对象的毫秒(0 ~ 999)。 |
parse() | 返回1970年1月1日午夜到指定日期(字符串)的毫秒数。 |
setDate() | 设置 Date 对象中月的某一天 (1 ~ 31)。 |
setMonth() | 设置 Date 对象中月份 (0 ~ 11)。 |
setFullYear() | 设置 Date 对象中的年份(四位数字)。 |
setYear() | 请使用 setFullYear() 方法代替。 |
setHours() | 设置 Date 对象中的小时 (0 ~ 23)。 |
setMinutes() | 设置 Date 对象中的分钟 (0 ~ 59)。 |
setSeconds() | 设置 Date 对象中的秒钟 (0 ~ 59)。 |
setMilliseconds() | 设置 Date 对象中的毫秒 (0 ~ 999)。 |
setTime() | 以毫秒设置 Date 对象。 |
setUTCDate() | 根据世界时设置 Date 对象中月份的一天 (1 ~ 31)。 |
setUTCMonth() | 根据世界时设置 Date 对象中的月份 (0 ~ 11)。 |
setUTCFullYear() | 根据世界时设置 Date 对象中的年份(四位数字)。 |
setUTCHours() | 根据世界时设置 Date 对象中的小时 (0 ~ 23)。 |
setUTCMinutes() | 根据世界时设置 Date 对象中的分钟 (0 ~ 59)。 |
setUTCSeconds() | 根据世界时设置 Date 对象中的秒钟 (0 ~ 59)。 |
setUTCMilliseconds() | 根据世界时设置 Date 对象中的毫秒 (0 ~ 999)。 |
toSource() | 返回该对象的源代码。 |
toString() | 把 Date 对象转换为字符串。 |
toTimeString() | 把 Date 对象的时间部分转换为字符串。 |
toDateString() | 把 Date 对象的日期部分转换为字符串。 |
toGMTString() | 请使用 toUTCString() 方法代替。 |
toUTCString() | 根据世界时,把 Date 对象转换为字符串。 |
toLocaleString() | 根据本地时间格式,把 Date 对象转换为字符串。 |
toLocaleTimeString() | 根据本地时间格式,把 Date 对象的时间部分转换为字符串。 |
toLocaleDateString() | 根据本地时间格式,把 Date 对象的日期部分转换为字符串。 |
UTC() | 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。 |
valueOf() | 返回 Date 对象的原始值。 |
语句和异常
1. 条件语句
条件语句用于基于不同的条件来执行不同的动作。
在 JavaScript 中,我们可使用以下条件语句:
- if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码
- if...else 语句 - 当条件为 true 时执行代码,当条件为 false 时执行其他代码
- if...else if....else 语句 - 使用该语句来选择多个代码块之一来执行
- switch 语句 - 使用该语句来选择多个代码块之一来执行
if语句
当条件为True时,才会执行代码:
if (条件1){ 语句 } else if (条件2){ 条件1不成立,如果2成立,执行 } else if (条件3){ 条件1和2不成立,3成立,执行 } else{ 当上述条件都不成立,会执行这里的代码 }
switch语句,个人感觉有点类似shell中的case
语法:
switch(表达式){ //表达式通常是一个变量,随后表达式的值和结构中的每个case的值作比较... case 1: 执行代码; break; case 2: 执行代码; break; default: 表达式与case1和case2不同时执行的代码; }
2. 循环
JavaScript*三种循环:
var names = ["tom","jerry","sam","jack"]; console.log(typeof(names)); for (var i=0;i<names.length;i++){ console.log(i,names[i]); }
var names = ["tom","jerry","sam","jack"]; for (var key in names){ console.log(key); console.log(names.key); }
var names = ["tom","jerry'","sam","jack"]; var i = 0; while (i<=names.length){ console.log(names[i]); i++ } //不要忘了循环里可以有continue和break
3. 异常处理
try{ //代码块,从上往下解释执行,抛出异常后这个代码块就会中止运行 throw Error('papapa'); //主动抛出异常 } catch(e){ //如果try代码块里跑出来异常,catch中的代码块就会执行,和Python中Except一样 //e是一个局部变量,用来指向Error对象或者其他跑出异常的对象 } finally{ //无论是否有一场,finally中的代码块总会执行 }
函数
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
function fun_name(){ //function是关键字 fun_name: 函数名 //代码块 }
PS:JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数。
JavaScript中有三类函数:
- 普通函数
- 匿名函数
- 自执行函数
//普通函数 function f1(arg){ return "普通函数" } //匿名函数 var f2 = function(arg){ return "匿名函数"; } //自执行函数 (function(arg){ return arg; }("自执行函数")
PS: 对于JavaScript中函数参数,实际参数的个数可能小于形式参数的个数,函数内的特殊值arguments中封装了所有实际参数。
2. 作用域
JavaScript中每个函数都有自己的作用域,当出现函数嵌套时,就出现了作用域链。当内层函数使用变量时,会根据作用域链从内到外一层层的循环,如果不存在,则异常。
切记:所有的作用域在创建函数且未执行时候就已经存在。
五句话搞明白:
- 1. JavaScript中无块级作用域
- JavaScript新版本中的let添加后也可以是一个块级作用域,但是目前为止还不太通用
- 2. JavaScript采用函数作用域
- 3. JavaScript的作用域链
- 由内向外一层一层找
- 4. JavaScript的作用域链执行前已经创建
- PS: 和Python一样
- 一个函数是一个作用域
- 5. 声明提前
function f1(){ var arg = 'heiheihei'; function f2(){ console.log(arg) } return f2; } res = f1() res() //执行结果是heiheihei
function f1(){ var arg = 'heiheihei'; function f2(){ console.log(arg); } arg = 'papapa'; return f2; } res = f1(); res() //执行结果是papapa
PS: 记住那五句话就可以搞明白作用域.
声明提前,在JavaScript引擎“预编译”时进行.
3. 闭包
「闭包」,是指拥有多个变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
闭包是个函数,而它「记住了周围发生了什么」。表现为由「一个函数」体中定义了「另个函数」
由于作用域链只能从内向外找,默认外部无法获取函数内部变量。闭包,在外部获取函数内部的变量。
闭包其实就是能够读取其他函数内部变量的函数,也就是将函数内部和函数外部连接起来的一座桥梁.
闭包的用途:
- 读取函数内部的变量
- 将这些变量始终保持在内存中;
使用闭包的注意点
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
function f1(){ var arg = 'heiheihei'; function f2(){ console.log(arg); } arg = 'papapa'; return f2; } res = f1(); res()
4. 面向对象
function f1(name,age){ this.Name = name; //Python中关键字是self,但是在JavaScript中这是一种伪面向对象 this.Age = age; this.Func = function(arg){ return this.Name + arg; } } var obj = new f1('Tom','2'); var res = obj.Func('Mouse'); console.log(res); //TomMouse
- f1是构造函数
- this指的是对象
- 创建对象时需要使用new关键字
上面代码中每个对象中均保存了一个相同的Func函数,从而浪费内存。使用原型和可以解决该问题:
function f1(name,age) { this.Name = name; this.Age = age; } f1.prototype = { GetInfo: function(){ return this.Name + this.Age; }, Func: function(arg) { return this.Name + arg; } } var obj = new f1('Tom','2'); var res = obj.Func('Mouse'); console.log(res); //TomMouse
练习题
对话框:
.hide{
display:none;
}
1. 按钮
2. 点击按钮执行一个JavaScript
3. 函数内:
找到两个div, hide移除
4. 按钮:
找到两个div, hide加上
参考:
- http://www.cnblogs.com/wupeiqi/articles/5602773.html
- http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
- http://www.w3school.com.cn/js/