【Python之路Day15】前端知识篇之JavaScript

基础

JavaScript是Web编程语言,由浏览器来编译并运行,现在基本上所有的HTML页面都使用JavaScript。

JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。

为什么学习 JavaScript?

JavaScript web 开发人员必须学习的 3 门语言中的一门:

  1. HTML 定义了网页的内容
  2. CSS 描述了网页的布局
  3. 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/
原文地址:https://www.cnblogs.com/dubq/p/5781065.html