一、什么是变量
从字面上看,变量是可变的量;从编程角度讲,变量是用于存储某种/某些数值的存储器。我们可以把变量看做一个盒子,为了区分盒子,可以用BOX1,BOX2等名称代表不同盒子,BOX1就是盒子的名字。
定义变量使用关键字var var 变量名
变量名可以任意取名,但要遵循命名规则:
1.变量必须使用字母、下划线或者美元符开始。2.然后可以使用任意多个英文字母、数字、下划线或者美元符组成。3.不能使用Javascript关键词与Javascript保留字。
变量要先声明再赋值
var mychar;
mychar="javascript";
var mynum = 6;
你可以使用 undefined 来判断变量是否已赋值.
var input;
if{
doThis;
} else {
doThat;
}
undefined 值在布尔类型环境中会被当作 false。例如,下面的代码将会执行函数 myFunction,因为数组myArray中的元素未被赋值:
var myArray = [];
if {
myFunction;
}
数值类型环境中 undefined 值会被转换为 NaN。
var a;
// 计算为 NaN
a + 2;
当你对一个 null 变量求值时,空值 null 在数值类型环境中会被当作0来对待,而布尔类型环境中会被当作 false。例如:
var n = null;
typeof;
// "object"
// The Null type has exactly one value, called null.
console.log;// 0
变量可以重复赋值
var mychar;
mychar="javascript";
mychar="hello";
注意:
在JS中区分大小写,如变量mychar与myChar是不一样的,表示是两个变量。变量虽然也可以不声明,直接使用,但不规范,需要先声明,后使用。
变量的作用域
在所有函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问。在函数内部声明的变量,叫做局部变量,因为它只能在该函数内部访问。
ECMAscript 6 之前的Javascript没有 语句块 作用域;相反,语句块中声明的变量将成为语句块所在代码段的局部变量。例如,如下的代码将在控制台输出 5,因为 x 的作用域是声明了 x 的那个函数,而不是 if 语句块。
if {
var x = 5;
}
console.log; // 5
如果使用 ECMAscript 6 中的 let 声明,上述行为将发生变化。
if {
let y = 5;
}
console.log;// ReferenceError: y is not defined
变量的数据类型
1、String: 字符串。 要表示变量的值是字符串,你必须将它们用引号包裹起来。2、Number: 数字。不用引号包围。3、Boolean: 布尔值。一个 True/False 值。 true/false 是 JS 里的特殊关键字,不需要引号。4、Object: 对象,基本上 Javascript 里的任何东西都是对象,而且都可以被储存在变量里。将这个牢记于心。Function Array 一种允许你存储多个值在一个引用里的结构。Date RegExp 5、Null 6、Undefined 7、Symbol 8、Error
二、什么是函数
函数是完成某个特定功能的一组语句。如没有函数,完成任务可能需要五行、十行、甚至更多的代码。这时我们就可以把完成特定功能的代码块放到一个函数里,直接调用这个函数,就省重复输入大量代码的麻烦。
基本语法
function定义函数的关键字。
函数调用:只需直接在需要的位置写函数就ok了
function add2{
var sum = 3 + 2;
alert;
}
add2; // 函数调用
三、输出内容: 可用于直接向 HTML 输出流写内容。简单的说就是直接在网页中输出内容。
第一种:输出内容用""括起,直接输出""号内的内容。
第二种:通过变量,输出内容
第三种:输出多项内容,内容之间用+号连接。
第四种:输出HTML标签,并起作用,标签使用""括起来。
alert
输出内容,可以是字符串或变量,与 document.write
相似。
四、确认
常用于允许用户做选择的动作,如:“你对吗?”等。弹出对话框。
/confirm/i;
str:在消息对话框中要显示的文本返回值: Boolean值:当用户点击"确定"按钮时,返回true;当用户点击"取消"按钮时,返回false
通过返回值可以判断用户点击了什么按钮
消息对话框是排它的,即用户在点击对话框按钮前,不能进行任何其它操作
五、提问
prompt 弹出消息对话框,通常用于询问一些需要与用户交互的信息。弹出消息对话框。
prompt;
str1: 要显示在消息对话框中的文本,不可修改str2:文本框中的内容,可以修改
返回值:
点击确定按钮,文本框中的内容将作为函数返回值点击取消按钮,将返回null
var myname=prompt;
if
{ alert;}
else
{ alert;}
注:在用户点击对话框的按钮前,不能进行任何其它操作。
六、打开新窗口
open 方法可以查找一个已经存在或者新建的浏览器窗口。
window.open
URL:可选参数,在窗口中要显示网页的网址或路径。如果省略这个参数,或者它的值是空字符串,那么窗口就不显示任何文档。窗口名称:可选参数,被打开窗口的名称。1.该名称由字母、数字和下划线字符组成。2."_top"、"_blank"、"_self"具有特殊意义的名称。_blank:在新窗口显示目标网页。 _self:在当前窗口显示目标网页。 _top:框架网页中在上部窗口中显示目标网页。3.相同 name 的窗口只能创建一个,要想创建多个窗口则 name 不能相同。4.name 不能包含有空格。参数字符串:可选参数,设置窗口参数,各参数用逗号隔开。
例如:打开 http://www.imooc.com网站,大小为300px * 200px,无菜单,无工具栏,无状态栏,有滚动条窗口:
七、关闭窗口
window.close; //关闭本窗口
<窗口对象>.close; //关闭指定的窗口
例如:关闭新建的窗口。
注意:上面代码在打开新窗口的同时,关闭该窗口,看不到被打开的窗口。
八、DOM
文档对象模型DOM定义访问和处理HTML文档的标准方法。DOM 将HTML文档呈现为带有元素、属性和文本的树结构。HTML文档可以说由节点构成的集合,三种常见的DOM节点:元素节点:上图中、、
等都是元素节点,即标签。文本节点:向用户展示的内容,如<li>...
中的Javascript、DOM、CSS等文本.属性节点:元素属性,如标签的链接属性href="http://www.imooc.com"。
1、通过ID获取元素
document.getElementById
注:获取的元素是一个对象,如想对元素进行操作,我们要通过它的属性或方法。
Javascript
结果:null或[object HTMLParagraphElement]
2、innerHTML 属性
innerHTML 属性用于获取或替换 HTML 元素的内容。Object.innerHTML
1.Object是获取的元素对象,如通过document.getElementById获取的元素。2.注意书写,innerHTML区分大小写。
3、改变 HTML 样式
Javascript使网页显示动态效果并实现与用户交互功能。Object.style.property=new style;
注意:Object是获取的元素对象,如通过document.getElementById获取的元素。I love Javascript
4、显示和隐藏
Object.style.display = value
注意:Object是获取的元素对象,如通过document.getElementById获取的元素。
5、控制类名
className 属性设置或返回元素的class 属性。object.className = classname
1.获取元素的class 属性为网页内的某个元素指定一个css样式来更改该元素的外观
Javascript使网页显示动态效果并实现与用户交互功能。 Javascript使网页显示动态效果并实现与用户交互功能。
nclick="add"/>
nclick="modify"/>
``
九、运算符
相等: ===
它将测试两个值是否相等,而且会返回一个 true/false 值。
非,不等:! 、 !=
经常与相等运算一起使用,非运算符在JS中表示逻辑非——它也返回一个布尔值。原本的值是 true ,但是返回了 false 因为之后我们做了非运算:var myVariable = 3;
!myVariable === 3; // false
这里我们测试了" myVariable 是否等于 3"。这里返回了 false ,因为它等于 3。var myVariable = 3;
myVariable !== 3; // false
十、字符串
1、检索特定字符串字符
可以使用方括号符号返回字符串中的任何字符:如: var browserType = 'mozilla'; browserType[0]; // m
检索任何字符串的最后一个字符: browserType[browserType.length-1];
2、在字符串中查找子字符串并提取它
browserType.indexOf; // 2
browserType.indexOf; // -1
使用它来查找不包含子串“mozilla”的所有字符串实例,或者如果使用否定运算符,请执行以下操作if !== -1) {
// do stuff with the string
}
当你知道字符串中的子字符串开始的位置,以及想要结束的字符时,slice可以用来提取它。第一个参数是开始提取的字符位置,第二个参数是提取的最后一个字符后一位置browserType.slice; // moz
在某个字符之后提取字符串中的所有剩余字符,则不必包含第二个参数,而只需要包含要从中提取的字符位置 字符串中的其余字符browserType.slice; // zilla
3、转换大小写
var radData = 'My NaMe Is MuD';
radData.toLowerCase; // 转换成小写
radData.toUpperCase; // 转换成大写
4、替换字符串的某部分
使用replace方法将字符串中的一个子字符串替换为另一个子字符串需要两个参数 - 要被替换下的字符串和要被替换上的字符串注意,想要真正更新browserType变量的值反应在真实程序里,您需要设置变量的值等于刚才的操作结果;它不会自动更新子串的值。所以事实上你需要这样写:browserType = browserType.replace;
。
十一、数组
可以将数组中的任何项目存储在数组中 - 字符串,数字,对象,另一个变量,甚至另一个数组,也可以混合和匹配项目类型。var random = ['tree', 795, [0, 1, 2]];
1、访问和修改数组项
使用括号表示法访问数组中的各个项目,方式与访问字符串中的字母相同
var shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles'];
shopping;
shopping[0]; // returns "bread"
还可以通过简单地向单个数组项提供新值来修改数组中的项目。
shopping[0] = 'tahini';
shopping;
// shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]
请注意,数组中的数组称为多维数组。 您可以通过将两组方括号链接在一起来访问数组内的另一个数组。例如,要访问数组中的一个作为随机数组内的第三个项目的内容.var random = ['tree', 795, [0, 1, 2]];
random[2][2]; // return 2
2、字符串和数组之间的转换
split
:会看到一个包含在一个长长的字符串中的原始数据,您可能希望将有用的项目分成更有用的表单,然后对它们进行处理,例如将它们显示在数据表中。在其最简单的形式中,这需要一个参数,您要将字符串分隔的字符,并返回分隔符之间的子串,作为数组中的项 var myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';
var myArray = myData.split; // 用每个逗号分隔它 return: Manchester,London,Liverpool,Birmingham,Leeds,Carlisle
myArray;
myArray[0]; // the first item in the array
myArray[myArray.length-1]; // the last item in the array
也可以使用join
方法进行相反的操作
var myNewString = myArray.join; return: Manchester,London,Liverpool,Birmingham,Leeds,Carlisle
myNewString;
数组转换为字符串:toString
toString
可以比join
更简单,因为它不需要一个参数,但更有限制。 使用join可以指定不同的分隔符
3、添加和删除数组项
push
:需要添加一个或多个要添加到数组末尾的项目
myArray.push;
myArray;
myArray.push;
myArray;
var newLength = myArray.push;
数组中删除最后一个项目就像在其上运行pop
一样简单 myArray.pop;
var removedItem = myArray.pop;
unshift
和shift以完全相同的方式工作,只是它们分别作用于数组的开始处,而不是结尾处。
unshift
: 在数组的开始增加一个元素shift
: 删除数组的第一个元素
myArray.unshift;
myArray;
var removedItem = myArray.shift;
myArray;
removedItem;
十二、条件语句
1、if ... else
语句
if {
code to run if condition is true
} else {
run some other code instead
}
要测试的条件,放到括号里。这个条件会利用比较运算符进行比较,并且返回true或者 false。如果条件返回true,运行代码A,否则运行代码B注意:你不一定需要else和第二个花括号——下面的代码也是符合语法规则的: if {
code to run if condition is true
}
run some other code
不过,这里你需要注意——在这种情况下,第二段代码不被条件语句控制,所以它总会运行,不管条件返回的是true还是false。这不一定是一件坏事,但这可能不是你想要的——你经常只想要运行一段代码或者另一段,而不是两个都运行。
2、比较运算符
=== and !== — 判断一个值是否严格等于,或不等于另一个。< and > — 判断一个值是否小于,或大于另一个。<= and >= — 判断一个值是否小于或等于,或者大于或等于另一个。我们想特别提到测试布尔值,和一个通用模式,你会频繁遇到它,任何不是 false, undefined, null, 0, NaN 的值,或一个空字符串在作为条件语句进行测试时实际返回true,因此您可以简单地使用变量名称来测试它是否为真,甚至是否存在。例如:var cheese = 'Cheddar';
if {
console.log;
} else {
console.log;
}
var shoppingDone = false;
if { // don't need to explicitly specify '=== true'
var childsAllowance = 10;
} else {
var childsAllowance = 5;
}
3、嵌套if ... else
if {
if {
para.textContent = 'It is ' + temperature + ' degrees outside —nice and sunny. Let's go out to the beach, or the park, and get an icecream.';
} else if {
para.textContent = 'It is ' + temperature + ' degrees outside —REALLY HOT! If you want to go outside, make sure to put some suncreamon.';
}
}
4、逻辑运算符:AND,OR和NOT
如果要测试多个条件,而不需要编写嵌套if ... else语句,逻辑运算符可以帮助您。当在条件下使用时,前两个执行以下操作:&&
— 逻辑与; 使得并列两个或者更多的表达式成为可能,只有当这些表达式每一个都返回true时,整个表达式才会返回true.||
— 逻辑或; 当两个或者更多表达式当中的任何一个返回 true 则整个表达式将会返回 true.if {
para.textContent = 'It is ' + temperature + ' degrees outside —nice and sunny. Let's go out to the beach, or the park, and get an icecream.';
} else if {
para.textContent = 'It is ' + temperature + ' degrees outside —REALLY HOT! If you want to go outside, make sure to put some suncreamon.';
}
让我们快速看一个OR的例子: if {
console.log;
} else {
console.log;
}
逻辑运算符的最后一个, NOT, 用 ! 运算符表示, 可以用于对一个表达式取否. 让我们把NOT结合上一个例子里的OR看看: if ) {
console.log;
} else {
console.log;
}
在这一段代码中,如果OR所在的语句返回 true,则NOT运算符将会将其取否,于是整个表达式的返回值将会是false。您可以在任何结构中随意合并很多个逻辑表达式。接下来的例子将会只在OR两边的语句同时返回true时才会执行代码,这也就意味着整个AND语句将会返回true: if && ) {
// run the code
}
在条件语句中运用OR逻辑运算符最常见的错误是尝试声明变量后,仅检查该变量一次的情况下赋予很多个都会返回true的值,不同的值之间用 || 运算符分隔。比如:错误演示: if {
// run my code
}
在这个例子里 if 里的条件总为真,因为 7 的值总是为真. 这个条件实际意思是 "如果x等于5, 或者7为真 — 它总是成立的". 这不是我们想要的逻辑,为了 让它正常工作你必须指定每个OR表达式两边都是完整的检查:
if {
// run my code
}
5、switch语句
switch {
case choice1:
run this code
break;
case choice2:
run this code instead
break;
// include as many cases as you like
default:
actually, just run this code
}
6、三元运算符
用于测试一个条件,并返回一个值/表达,如果它是true,另一个是false-这种情况下是有用的,并且可以占用比if...else块较少的代码块。如果你只有两个通过true/ false条件选择。 run this code : run this code instead
var greeting = 'Happy birthday Mrs. Smith — we hope you have a great day!' : 'Good morning Mrs. Smith.';
在这里我们有一个变量叫做isBirthday- 如果它是true,我们给客人一个生日快乐的消息; 如果不是,我们给她标准的每日问候。你不需要用三元运算符设置变量值; 你也可以运行任何你喜欢的函数或代码行。以下实例显示了一个简单的主题选择器,其中该站点的样式应用了三元运算符。
This is my website
var select = document.querySelector;
var html = document.querySelector;
document.body.style.padding = '10px';
function update {
html.style.backgroundColor = bgColor;
html.style.color = textColor;
}
select.onchange = function {
update : update;
}
如果这返回true,我们运行update带有黑色和白色参数的函数,这意味着我们最终得到黑色的背景颜色和白色的文字颜色。如果返回false,我们运行update带有白色和黑色参数的函数,这意味着站点颜色被反转。
7、 一个简单的日历
`` `` `` `` `
` `` ``
十三、循环
1、for {
// code to run
}
var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin'];
var info = 'My cats are called ';
var para = document.querySelector;
for {
info += cats[i] + ', ';
}
para.textContent = info;
输出:My cats are called Bill, Jeff, Pete, Biggles, Jasmin,
理想情况下,我们想改变最后循环迭代中的连接,以便在句子末尾没有逗号。 for {
if {
info += 'and ' + cats[i] + '.';
} else {
info += cats[i] + ', ';
}
}
2、使用break退出循环
如果要在所有迭代完成之前退出循环,可以使用break语句。
var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975'];
var para = document.querySelector;
var input = document.querySelector;
var btn = document.querySelector;
`btn.addEventListener{` `// 我们将输入的值输入到一个名为searchName的变量中,然后清空文本输入并重新对准它,准备进行下一个搜索` `var searchName = input.value;` `input.value = '';` `input.focus;` `for{` `// 将当前联系人拆分为冒号字符,并将生成的两个值存储在名为splitContact的数组中` `var splitContact = contacts[i].split;` `// 使用条件语句来测试splitContact [0]是否等于输入的searchName。 如果是,我们在段落中输入一个字符串来报告联系人的号码,并使用break来结束循环` `// 在 迭代后,如果联系人姓名与输入的搜索不符,则段落文本设置为“未找到联系人”,循环继续迭代。` `if{` `para.textContent = splitContact[0] + ''s number is ' + splitContact[1] + '.';` `break;` `} else {` `para.textContent = 'Contact not found.';` `}` `}``}) `
3、使用continue跳过迭代
var para = document.querySelector;
var input = document.querySelector;
var btn = document.querySelector;
`var num = input.value;``for{` `var sqRoot = Math.sqrt; ` `// 用Math.sqrt找到每个数字的平方根,然后通过测试平方根是否是一个整数,当它被四舍五入到最接近的整数时,它是否与自身相同` `if !== sqRoot){` `continue;` `}``// 如果平方根和四舍五入的平方根不相等,则表示平方根不是整数,因此我们对此不感兴趣。 在这种情况下,我们使用continue语句跳过下一个循环迭代,而不在任何地方记录该数字。` `para.textContent += i + ' ';` `// 如果平方根是一个整数,我们完全跳过if块,所以continue语句不被执行; 相反,我们将当前i值加上一个空格连接到段落内容的末尾``}`
4、while语句和do ... while语句
while循环 -initializer
while {
// code to run
final-expression
}
-var i = 0;
while {
if {
info += 'and ' + cats[i] + '.';
} else {
info += cats[i] + ', ';
}
i++;
}
do...while循环非常类似但在while后提供了终止条件: -initializer
do {
// code to run
final-expression
} while
-var i = 0;
do {
if {
info += 'and ' + cats[i] + '.';
} else {
info += cats[i] + ', ';
}
i++;
} while ;
5、启动倒计时
// 方法一:
// var i = 10; // 初始化
// while { // 退出条件
// var para = document.createElement;
`// if{` `// para.textContent = 'Countdown' + i;` `// } else if{` `// para.textContent = 'Blast off!';` `// } else{` `// para.textContent = i;` `// }` `// output.appendChild;` `// i--; ` `// // 在循环中的代码运行之后,运行最后的条件,这只有在尚未达到退出条件时才会发生` `// }``// 方法二:` `// for{` `// var para = document.createElement; ` `// if{` `// para.textContent = 'Countdown' + i;` `// }else if{` `// para.textContent = 'Blast off!';` `// } else{` `// para.textContent = i;` `// }` `// output.appendChild;` `// }` `// 方法三:` `var i = 10;` `do { ` `// 花括号中的代码总是在检查之前运行一次,以查看是否应该再次执行。` `var para = document.createElement; ` `if{` `para.textContent = 'Countdown' + i;` `}else if{` `para.textContent = 'Blast off!';` `} else{` `para.textContent = i;` `}` `output.appendChild;` `i--;` `} while;`
6、填写来宾列表
var people = ['Chris', 'Anne', 'Colin', 'Terri', 'Phil', 'Lola', 'Sam', 'Kay', 'Bruce'];
var admitted = document.querySelector;
var refused = document.querySelector;
admitted.textContent = 'Admit: ';
refused.textContent = 'Refused: ';
`var i = 0;` `while{` `if{` `refused.textContent += people[i] + ', ';` `} else {` `admitted.textContent += people[i] + ', ';` `}` `i++;` `}` `refused.textContent = refused.textContent.slice + '.';` `admitted.textContent = admitted.textContent.slice + '.';`
十四、函数
1、浏览器内置函数
Javascript有许多内置的函数,可以让您做很多有用的事情,而无需自己编写所有的代码。事实上, 许多你调用浏览器内置函数时调用的代码并不是使用Javascript来编写——大多数调用浏览器后台的函数的代码,是使用像C++这样更低级的系统语言编写的,而不是像Javascript这样的web编程语言。
2、函数与方法
严格说来,内置浏览器函数并不是函数——它们是方法。函数和方法在很大程度上是可互换的.二者区别在于方法是在对象内定义的函数。内置浏览器功能和变量存储在结构化对象内,以使代码更加高效,易于处理。
3、自定义函数
自定义名称后面都带有括号,那么您使用的是自定义函数.
function draw {
ctx.clearRect;
for {
ctx.beginPath;
ctx.fillStyle = 'rgba';
ctx.arc, random, random, 0, 2 * Math.PI);
ctx.fill;
}
}
该函数在元素中绘制100个随机圆。每次我们想要这样做,我们可以使用这个函数来调用这个功能 draw;
函数可以从内部函数调用其他函数。以上函数例如调用random函数三次,由以下代码定义:function random {
return Math.floor*number);
}
我们需要这个函数,因为浏览器的内置Math.random函数只生成一个0到1之间的随机十进制数。我们想要一个0到一个指定数字之间的随机整数。
4、调用函数
通过将函数名包含在代码的某个地方,后跟圆括号来完成的 function myFunction {
alert;
}
myFunction
// calls the function once
5、匿名函数
没有函数名,不会自己做任何事情,通常使用匿名函数以及事件处理程序。例如,如果单击相关按钮,以下操作将在函数内运行代码: var myButton = document.querySelector;
myButton.onclick = function {
alert;
}
还可以将匿名函数分配为变量的值。 var myGreeting = function {
alert;
}
myGreeting;
有效地给变量一个名字;还可以将该函数分配为多个变量的值,例如: var anotherGreeting = function {
alert;
}
anotherGreeting;
但这只会令人费解,所以不要这样做!创建功能时,最好只要坚持下列形式: function myGreeting {
alert;
}
您将主要使用匿名函数来运行负载的代码以响应事件触发 - 使用事件处理程序。再次,这看起来像这样: myButton.onclick = function {
alert;
// I can put as much code
// inside here as I want
}
匿名函数也称为函数表达式。函数表达式与函数声明有一些区别。函数声明会进行声明提升,而函数表达式不会。
6、函数参数
一些函数需要在调用它们时指定参数 - 这些值需要包含在函数括号内,它需要正确地完成其工作。参数有时称为参数,属性或甚至属性例如,浏览器的内置Math.random函数不需要任何参数。当被调用时,它总是返回0到1之间的随机数: var myNumber = Math.random;
浏览器的内置字符串replace函数需要两个参数:在主字符串中查找的子字符串,以及用以下替换该字符串的子字符串: var myText = 'I am a string';
var newString = myText.replace;
当您需要指定多个参数时,它们以逗号分隔。还应该注意,有时参数是可选的 - 您不必指定它们。如果没有,该功能一般会采用某种默认行为。作为示例,数组join函数的参数是可选的:
var myArray = ['I', 'love', 'chocolate', 'frogs'];
var madeAString = myArray.join;
// returns 'I love chocolate frogs'
var madeAString = myArray.join;
// returns 'I,love,chocolate,frogs'
如果没有包含参数来指定加入/分隔符,默认情况下会使用逗号
7、函数作用域和冲突
创建一个函数时,函数内定义的变量和其他东西都在它们自己的单独的范围内, 意味着它们被锁在自己独立的隔间中, 不能从函数外代码其它函数内访问。所有函数的最外层被称为全局作用域。 在全局作用域内定义的值可以在任意地方访问。
8、函数内部的函数
function myBigFunction {
var myValue;
subFunction1;
subFunction2;
subFunction3;
}
function subFunction1 {
console.log;
}
function subFunction2 {
console.log;
}
function subFunction3 {
console.log;
}
只需确保在函数内使用的值正确的范围. 上面的例子会抛出一个错误ReferenceError:MyValue没有被定义,因为myValue变量与函数调用的范围相同, 函数定义内没有定义 - 调用函数时运行的实际代码。为了使这个工作,你必须将值作为参数传递给函数,如下所示: function myBigFunction {
var myValue = 1;
subFunction1;
subFunction2;
subFunction3;
}
function subFunction1 {
console.log;
}
function subFunction2 {
console.log;
}
function subFunction3 {
console.log;
}
十五、事件
在编程时系统内的发生的动作或者发生的事情— 系统会在事件出现的时候触发某种信号并且会提供一个自动加载某种动作的机制,比如在一个机场,当一架将起飞的飞机的跑道清理完成后,飞行员会收到一个信号,结果是他们开始起飞。在Web中, 事件在浏览器窗口中被触发并且通常被绑定到窗口内部的特定部分 — 可能是一个元素、一系列元素、被加载到这个窗口的 HTML 代码或者是整个浏览器窗口。每个可用的事件都会有一个事件处理器,也就是事件触发时会运行的代码块。当我们定义了一个用来回应事件被激发的代码块的时候,我们说我们注册了一个事件处理器。网络事件不是 Javascript 语言的核心——它们被定义成内置于浏览器的Javascript APIs。
1、使用网页事件的方式
事件处理器属性 var btn = document.querySelector;
btn.onclick = function {
var rndCol = 'rgb + ',' + random + ',' + random + ')';
document.body.style.backgroundColor = rndCol;
}
这个 onclick 是被用在这个情景下的事件处理器的属性,它就像 button 其他的属性
function bgChange {
var rndCol = 'rgb + ',' + random + ',' + random + ')';
document.body.style.backgroundColor = rndCol;
}
2、addEventListener和removeEventListener
这个函数和事件处理属性是类似的,但是语法略有不同 var btn = document.querySelector;
function bgChange {
var rndCol = 'rgb + ',' + random + ',' + random + ')';
document.body.style.backgroundColor = rndCol;
}
btn.addEventListener;
在addEventListener 函数中, 我们具体化了两个参数——我们想要将处理器应用上去的事件名称,和包含我们用来回应事件的函数的代码。注意将这些代码全部放到一个匿名函数中是可行的: btn.addEventListener {
var rndCol = 'rgb + ',' + random + ',' + random + ')';
document.body.style.backgroundColor = rndCol;
});
这个机制带来了一些相较于旧方式的优点。有一个相对应的方法,removeEventListener,这个方法移除事件监听器。例如,下面的代码将会移除上个代码块中的事件监听器: btn.removeEventListener;
这在简单个的、小型的项目中可能不是很有用,但是在大型的、复杂的项目中就非常有用了,可以非常高效地清除不用的事件处理器,另外在其他的一些场景中也非常有效——比如您需要在不同环境下运行不同的事件处理器,您只需要恰当地删除或者添加事件处理器即可您也可以给同一个监听器注册多个处理器,下面这种方式不能实现这一点:
myElement.onclick = functionA;
myElement.onclick = functionB;
第二行会覆盖第一行,但是下面这种方式就会正常工作了:
myElement.addEventListener;
myElement.addEventListener;
当元素被点击时两个函数都会工作:
3、 我该使用哪种机制?
第三种机制的主要优点是,如果需要的话,可以使用removeEventListener
删除事件处理程序代码,而且如果有需要,您可以向同一类型的元素添加多个监听器。例如,您可以在一个元素上多次调用,addEventListener { ... })
,并可在第二个参数中指定不同的函数。对于事件处理程序属性来说,这是不可能的,因为后面任何设置的属性都会尝试覆盖较早的属性。
4、其他事件概念
事件对象:有时候在事件处理函数内部,您可能会看到一个固定指定名称的参数,例如event,evt或简单的e。 这被称为事件对象,它被自动传递给事件处理函数,以提供额外的功能和信息。
function bgChange { var rndCol = 'rgb + ',' + random + ',' + random + ')'; e.target.style.backgroundColor = rndCol; console.log;}btn.addEventListener;
在这里,您可以看到我们在函数中包括一个事件对象,e,并在函数中设置背景颜色样式在e.target上 - 它指的是按钮本身。 事件对象 e 的target属性始终是事件刚刚发生的元素的引用。 所以在这个例子中,我们在按钮上设置一个随机的背景颜色,而不是页面。
当您要在多个元素上设置相同的事件处理程序时,e.target非常有用,并且在发生事件时对所有元素执行某些操作.
例如,你可能有一组16块方格,当它们被点击时就会消失。用e.target总是能准确选择当前操作的东西并执行操作让它消失,而不是必须以更困难的方式选择它。
我们使用Javascript创建了16个元素。接着我们使用 document.querySelectorAll选择全部的元素,然后遍历每一个,为每一个元素都添加一个onclick单击事件,每当它们点击时就会为背景添加一个随机颜色。
var ps = document.querySelectorAll;for { ps[i].onclick = function { e.target.style.backgroundColor = bgChange; }}完整代码
阻止默认行为
最常见的例子是Web表单,例如自定义注册表单。 当你填写详细信息并按提交按钮时,自然行为是将数据提交到服务器上的指定页面进行处理,并将浏览器重定向到某种“成功消息”页面当用户没有正确提交数据时,麻烦就来了 - 作为开发人员,你希望停止提交信息给服务器,并给他们一个错误提示,告诉他们什么做错了,以及需要做些什么来修正错误。 一些浏览器支持自动的表单数据验证功能,但由于许多浏览器不支持,因此建议你不要依赖这些功能,并实现自己的验证检查。 我们来看一个简单的例子。
这里我们用一个onsubmit事件处理程序来实现一个非常简单的检查,用于测试文本字段是否为空。 如果是,我们在事件对象上调用preventDefault函数,这样就停止了表单提交,然后在我们表单下面的段落中显示一条错误消息,告诉用户什么是错误的:
var form = document.querySelector;
var fname = document.getElementById;
var lname = document.getElementById;
var submit = document.getElementById;
var para = document.querySelector;
form.onsubmit = function {
if {
e.preventDefault;
para.textContent = 'You need to fill in both names!';
}
}
显然,这是一种非常弱的表单验证——例如,用户输入空格或数字提交表单,表单验证并不会阻止用户提交——这不是我们例子想要达到的目的。事件冒泡及捕获
5、事件冒泡及捕获
事件冒泡和捕捉是两种机制,主要描述当在一个元素上有两个相同类型的事件处理器被激活会发生什么。
比如有个父元素的事件,然后 子元素是, 当点击播放的时候,也会触发了隐藏事件。要解决的话 可以在子元素的事件里加上 stopPropagation时,现代浏览器运行两个不同的阶段 - 捕获阶段和冒泡阶段。 在捕获阶段:
浏览器检查元素的最外层祖先,是否在捕获阶段中注册了一个onclick事件处理程序,如果是,则运行它。然后,它移动到中的下一个元素,并执行相同的操作,然后是下一个元素,依此类推,直到到达实际点击的元素。
在冒泡阶段,恰恰相反:
浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,如果是,则运行它。然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达元素。
2、用 stopPropagation 修复问题
标准事件对象具有可用的名为 stopPropagation的函数, 当在事件对象上调用该函数时,它只会让当前事件处理程序运行,但事件不会在冒泡链上进一步扩大,因此将不会有更多事件处理器被运行。所以,我们可以通过改变前面代码块中的第二个处理函数来解决当前的问题: video.onclick = function {
e.stopPropagation;
video.play;
};
注解: 为什么我们要弄清楚捕捉和冒泡呢?那是因为,在过去糟糕的日子里,浏览器的兼容性比现在要小得多,Netscape只使用事件捕获,而Internet Explorer只使用事件冒泡。当W3C决定尝试规范这些行为并达成共识时,他们最终得到了包括这两种情况的系统,最终被应用在现在浏览器里。注解: 如上所述,默认情况下,所有事件处理程序都是在冒泡阶段注册的,这在大多数情况下更有意义。如果您真的想在捕获阶段注册一个事件,那么您可以通过使用addEventListener注册您的处理程序,并将可选的第三个属性设置为true。参考例子1 参考例子2
3、事件委托 参考例子
冒泡还允许我们利用事件委托——这个概念依赖于这样一个事实,如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是每个子节点单独设置事件监听器。
一个很好的例子是一系列列表项,如果你想让每个列表点击时弹出一条信息,您可以将click单击事件监听器设置在父元素上,它将会冒泡到列表项上。
十六、对象
在 Javascript 中,大多数事物都是对象, 从作为核心功能的字符串和数组,到建立在 Javascript 之上的浏览器 API。你甚至可以自己创建对象,将相关的函数和变量封装打包成便捷的数据容器。理解这种面向对象 的特性对于进一步学习 Javascript 语言知识是必不可少的。
1、对象基础
对象是一个包含相关数据和方法的集合
一个对象由许多的成员组成,每一个成员都拥有一个名字,和一个值。每一个名字/值对被逗号分隔开,并且名字和值之间由冒号分隔,语法规则如下所示:
var objectName = {
member1Name : member1Value,
member2Name : member2Value,
member3Name : member3Value
}
var person = {
name : ['Bob', 'Smith'],
age : 32,
gender : 'male',
interests : ['music', 'skiing'],
bio : function {
alert;
},
greeting: function {
alert;
}
};
对象成员的值可以是任意的,在我们的person对象里有字符串,数字,两个数组,两个函数。前4个成员是资料项目,被称为对象的属性,后两个成员是函数,允许对象对资料做一些操作,被称为对象的方法
一个如上所示的对象被称之为对象的字面量——手动的写出对象的内容来创建一个对象。不同于从类实例化一个对象,
当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来创建一个对象,举例来说,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,而且比起数组更为易用,因为你使用名字来标识这些资料。
2、点表示法
访问对象的属性和方法,当你想访问对象内部的属性或方法时,然后是一个点,紧接着是你想要访问的项目,标识可以是简单属性的名字,或者是数组属性的一个子元素,又或者是对象的方法调用。 person.age
person.interests[1]
person.bio
子命名空间:可以用一个对象来做另一个对象成员的值 name : ['Bob', 'Smith'],
改成 name : {
first : 'Bob',
last : 'Smith'
},
访问:链式的再使用一次点表示法 person.name.first
person.name.last
3、括号表示法
另外一种访问属性的方式是使用括号表示法 person.age
person.name.first
换成: person['age']
person['name']['first']
这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组了——对象做了字符串到值的映射,而数组做的是数字到值的映射。
4、设置对象成员
person.age = 45
person['name']['last'] = 'Cratchit'
设置成员并不意味着你只能更新已经存在的属性的值,你完全可以创建新的成员,尝试以下代码: person['eyes'] = 'hazel'
person.farewell = function { alert }
括号表示法一个有用的地方是它不仅可以动态的去设置对象成员的值,还可以动态的去设置成员的名字。
比如说,我们想让用户能够在他们的数据里存储自己定义的值类型,通过两个input框来输入成员的名字和值,通过以下代码获取用户输入的值:
var myDataName = nameInput.value
var myDataValue = namevalue.value
我们可以这样把这个新的成员的名字和值加到person对象里:
person[myDataName] = myDataValue
5、"this"的含义
this 指向了代码所在的对象。在字面量的对象里this看起来不是很有用,但是当你动态创建一个对象时它是非常有用的,之后你会更清楚它的用途。