【Python之路Day15】前端知识篇之JavaScript
基础
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"
View Code
concat(value, …) 拼接
name "daniel" var age = 18; name.concat(age) "daniel18"
View Code
indexOf(substring,start) 子序列位置
name.indexOf("a")
1
View Code
lastIndexOf(substring,start) 子序列位置
var name = "daniel"; undefined name.lastIndexOf("an",1) 1
View Code
substring(
from
, to) 根据索引获取子序列
name "daniel" name.substring(1,5) //类似于python的切片,顾首不顾尾 "anie" name.substring(1,2) "a" name.substring(1,3)
View Code
slice
(start, end) 切片
name "daniel" name.slice(1,3) "an" name.slice(1,name.lenght) "aniel"
View Code
toLowerCase() 小写
name "DANIEL" name.toLocaleLowerCase() "daniel"
View Code
toUpperCase() 大写
var name = "tom"; undefined name.toUpperCase() "TOM"
View Code
split(delimiter, limit) 分割
var s1 = "I name is daniel"; undefined s1 "I name is daniel" s1.split() ["I name is daniel"] //分割后变成一个数组,也就是Python中的列表
View Code
search(regexp) 从头开始匹配,返回匹配成功的第一个位置(g无效)
s1 "I name is daniel" s1.search("I") 0 s1.search("d") 10
View Code
match(regexp) 全局搜索,如果正则中有g表示找到全部,否则只找到第一个。
s1.match("a"); ["a"] s1.match("a.*"); ["ame is daniel"] s1.match("a.+"); ["ame is daniel"]
View Code
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"
View Code
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
parseInt
var n2 = 18; undefined var res = parseFloat(n2); undefined res 18
parseFloat
res 18 isNaN(res) false n = "w" "w" isNaN(n); true
isNaN
n1 18.332 isFinite(n1); true n3 = 12309394903990390190230; 1.230939490399039e+22 isFinite(n3) true n4 = 3; 3 isFinite(n4); true //无穷大是一个相对值,其实我也不知道到底多少才是无穷大...
isFinite
更多数值计算:
常量
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
deleteCount为0
girls ["Adele", "Barbara", "Selina", "Eda"] girls.splice(1,1,\'Bea\'); ["Barbara"] girls ["Adele", "Bea", "Selina", "Eda"] //替换制定位置的值为value
deleteCount为1
girls ["Adele", "Bea", "Selina", "Eda"] girls.splice(1,1); ["Bea"] girls ["Adele", "Selina", "Eda"]
deleteCount为1时不指定Val
slice
( ) 切片
girls ["Adele", "Selina", "Eda"] girls.slice(1,3); ["Selina", "Eda"] girls.slice(1); ["Selina", "Eda"] girls.slice(0); ["Adele", "Selina", "Eda"]
View Code
reverse( ) 反转
girls ["Adele", "Selina", "Eda"] girls.reverse() ["Eda", "Selina", "Adele"]
View Code
join(sep) 将数组元素连接起来以构建一个字符串
girls ["Eda", "Selina", "Adele"] s1 = \'hehe\'; "hehe" girls.join(s1); "EdaheheSelinaheheAdele"
View Code
concat(val,..) 扩展数组
var boy = Array("Tom","Jerry","Sam"); undefined girls ["Eda", "Selina", "Adele"] girls.concat(boy); ["Eda", "Selina", "Adele", "Tom", "Jerry", "Sam"]
View Code
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
View Code
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=林丹李宗伟里约"
decodeURI
decodeURIComponent(url)
"https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"
decodeURIComponent
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"
encodeURI
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"
encodeURIComponent
scape(url2)
"https%3A//www.google.com.hk/%3Fgws_rd%3Dssl%23newwindow%3D1%26safe%3Dstrict%26q%3D%u6797%u4E39%u674E%u5B97%u4F1F%u91CC%u7EA6"
scape
unescape(url2)
"https://www.google.com.hk/?gws_rd=ssl#newwindow=1&safe=strict&q=林丹李宗伟里约"
unescape
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(…)
URIError
3. eval
JavaScript中的eval是Python中eval和exec的合集,既可以编译代码也可以获取返回值。
eval()
var a="1+2+3" undefined a "1+2+3" eval(a) 6
eval
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(…)
EvalError
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 (中国标准时间)
View Code
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/