前端笔记之JavaScript(七)深入函数&DOM那点事
一、函数补充
1.1 arguments类数组对象
arguments 是一个对应于传递给函数的参数的类数组对象。
在函数中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
在其它编程语言中,比如java:如果一个函数被定义过两次,每次参数个数都不同。相当于定义了两个不同的函数,根据参数个数不同,会选择不同的函数执行。一个函数名定义了两个函数,称为“函数重载”(overloaded)。
复习一下函数,定义函数时,参数要罗列在圆括号中,这些参数,叫“形参”:
function fun(a,b,c){
console.log(a,b,c);
}
function fun(a,b){
console.log(a,b);
}
fun(1,2);
fun(1,2,3); //合法的,参数多了和少了,都不报错。
调用函数时,传的参数叫“实参”,JS不要求形参和实参数量一样多。
实际上,这种叫做方法的重载。在Java中,同一个函数名,但是参数个数不一样,视为是两个函数。
也就是说,Java中能够定义两个同名函数。
同名的两个function,都是fun函数,java允许这样做,但是js没有这种操作。
JavaScript函数中有一个非常强大的参数,就是每一个函数内部,都可以使用arguments这个类数组对象。
这个arguments对象,就是涵盖了所有实参(调用函数时传入的所有实际参数)
function fun(a,b){
console.log(a,b); //等价于arguments[0]和arguments[1]
//此时函数内部,arguments就有下标,依次等于实参的值
console.log(arguments);
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
arguments[5] = 88888;
console.log(arguments[8]);
console.log(arguments.length); //输出实参的个数
console.log(arguments.callee); //callee等价于函数本身
console.log(arguments.callee.length); //callee的length是形参的个数
console.log(arguments.callee.name); //函数的名称
}
fun(10,20,30,40,50,88,99,100,999);
// console.log(arguments); 由于是函数内部的对象,所以函数外是没有定义的,报错。
arguments的功能,可以模拟函数的重载,使用一个函数根据参数的个数不同,有不同的作用。
比如我们设计一个sum函数:
如果传进来一个参数,就得到当前值+1
如果传进来两个参数,就返回两个数的和
function sum(a,b){
switch(arguments.length){
case 1:
return ++a;
break;
case 2:
return a + b;
break;
}
// if(arguments.length == 1){
// return ++a;
// }else if(arguments.length == 2){
// return a + b;
// return arguments[0] + arguments[1];
// }
}
console.log(sum(10));
console.log(sum(10,88));
设计一个无限参的函数:累加和
function sum(){
var count = 0; //累加器
for(var i = 0; i < arguments.length;i++){
count += arguments[i];
}
return count;
}
console.log(sum(10,20,30,88,99,100,888,999));
设计一个函数,check如果只有一个参数,那么就检测这个数是否是偶数,如果有两个参数,检测这两个参数奇偶性是否相同:
function check(){
switch(arguments.length){
case 1:
return arguments[0] % 2 == 0 ? true : false;
break;
case 2:
return (arguments[0] + arguments[1]) % 2 == 0 ? true : false;
break;
default:
// console.log("输入错误,请检测,只支持1到2个参数!");
throw new Error("输入错误,请检测,只支持1到2个参数!");
}
}
console.log(check(8));
console.log(check(8,8));
console.log(check(8,8,8));
1.2 IIFE
IIFE:Immediately-Invoked Function Expression,即时调用函数表达式。
如果一个函数,在定义的时候,就想直接调用它,就是一个IIFE。
函数执行方法:在函数名或变量名后面加()运算符。
函数关键字形式:定义时直接在后面加()执行。
function fun(){ console.log("哈哈"); }(); |
不能给函数关键字方法直接()调用。
函数表达式形式:能立即执行,函数在赋值给变量时就已经被矮化成表达式了,可以直接在后面加圆括号执行
var fun = function(){ console.log("哈哈"); }(); |
结论:如果函数能被矮化成表达式,就能在定义时直接调用,就能实现IIFE。
函数矮化为表达式的方法:在函数定义之前加运算符。
数学运算符中:+ - ()符号,其他不能用。
逻辑运算符中:!
其他:~
注意也可以不写函数名。
+function (){
console.log("哈哈");
}();
-function (){
console.log("哈哈");
}();
!function (){
console.log("哈哈");
}();
~function (){
console.log("哈哈");
}();
(function (){
console.log("哈哈");
})();
(function (){
console.log("哈哈");
}());
IIFE还可以键函数传参,IIFE能够关住函数的作用域。在使用某个变量时,如果变量定义在函数内,或函数的参数,只会使用立即调用的变量值,不会对被人造成影响。
(function fun(a){
console.log(a);
})(8);
fun(5); //IIFE关住fun的作用域,外面找不到fun函数的定义
IIFE可以不写函数名,写匿名函数;IIFE关住函数的作用域,可以用于解决函数闭包带来的错误影响。
最标准常用的IIFE格式:所以IIFE里面的函数,都是匿名函数。
(function fun(a){ console.log(a); })(8); |
1.3结合数组观察闭包
我们说过,数组中,什么都可以放,比如String、Number、Boolean、undefined、function等。
通过动态的方法,遍历数组,给数组每一项添加一个函数:
var arr = []; //空数组接收函数的定义
for(var i = 0;i <= 10;i++){
//函数定义时,作用域全局的,全局中有个变量i
//函数值只是定义给数组的每一项,并不会执行
//函数这个闭包,记住了全局作用域,里面有个i,记住了自己内部的语句
arr[i] = function(){
console.log(i);
}
}
console.log(arr);
arr[0](); //调用了数值中的函数,执行了console.log(i)
arr[1](); //调用了数值中的函数,执行了console.log(i)
...
arr[9](); //调用了数值中的函数,执行了console.log(i)
arr[10]();//调用了数值中的函数,执行了console.log(i)
注意:上面的案例并没有实现想要的结果,我们希望每一项输出时,i对应的值应该与每次的下标相同,闭包记住仅仅是一个函数的定义,记住内部的语句输出i。
输出的都是11,而不是预想的0~10,原因是每个函数定义时,都产生闭包,函数只认识i,而不是把i这个值复制一份记忆住,而是动态的认识这个i。i调用时得几,这个函数的i就是几。
所以在调用函数时,i已经变成11,所以数组中每个函数都是11。
想要实现输出i与下标相同的值,解决方法:
var arr = []; //空数组接收函数的定义
for(var i = 0;i <= 10;i++){
//函数定义时,作用域全局的,全局中有个变量i
//函数值只是定义给数组的每一项,并不会执行
//函数这个闭包,记住了全局作用域,里面有个i,记住了自己内部的语句
// (arr[i] = function(){
// console.log("下标:"+ i);
// })();
(function(a){
arr[a] = function(){
console.log("下标:"+ a);
}
})(i);
}
// console.log(arr);
arr[0](); //调用了数值中的函数,执行了console.log(i)
arr[1](); //调用了数值中的函数,执行了console.log(i)
...
arr[9](); //调用了数值中的函数,执行了console.log(i)
arr[10](); //调用了数值中的函数,执行了console.log(i)
二、DOM
前期课程中,学习的ECMAscript语言核心部分,都是在控制台,天天console.log()、prompt()等。
之前学的属于语言,了解JS这个语言的特性,从今天开始要学习JS控制页面上的元素。回归到操作HTML和CSS。
2.1 DOM概述
DOM(Document Object Model,文档对象模型)描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。使用JavaScript操作HTML,不是在操作字符串,而是在操作节点,极大地降低了编程难度。
DOM规范在1998年10月制定,称为“DOM1级规范”。随着ECMAScript的升级,DOM也发展出了2级规范、3级规范。另外,早于1998年的DOM也有事实上的标准,我们称为0级规范。
DOM对很多东西做了抽象,提供了丰富的API:取得元素、css样式、事件、运动、元素尺寸位置、节点操作。每个知识体系都非常庞大,千丝万缕。我们今天的课程,把一些线头都掐出来,日后的课程深入研究每个线头。
<body>
<div id="box"></div>
<img src="data:images/ssh.jpg" id="timg" title="邵老师" >
</body>
<script type="text/javascript">
//获取HTML标签元素
var timg = document.getElementById("timg");
var oBox = document.getElementById("box");
//给图片添加点击事件,让img标签修改src和title属性
timg.onclick = function(){
timg.src = "images/timg.jpg";
timg.title = "考拉吃树叶";
timg.width = "300";
}
//点击盒子变色
oBox.onclick = function(){
oBox.style.backgroundColor = "skyblue";
}
</script>
2.2获取HTML标签元素
HTML负责页面的布局、结构。JS要操作HTML标签,第一件事就是要得到这个标签。
说白了就是把HTML标签拿到JS里面来操作。
JS中,最基本的得到标签元素的方法有两个:
document.getElementById(); //通id获取一个标签元素 document.getElementsByTagName(); //通过标签名获取一组元素 |
JS通过document对象(表示文档集合),它表示整个页面,有很多属性和方法,包含绝大多数的特征和操作。
学习DOM说白了就是学习document对象
console.log(document.URL); //获取当前文件路径 console.log(document.title); //获取当前页面标题 document.title = "爱前端官网"; //设置当前页面标题 |
DOM操作,往往都是从某个HTML元素开始,然后对这个元素进行一些操作,所以得到元素是非常关键,得到元素的操作可以使用document对象的方法。
注意:
1、方法名称都是驼峰命名法,首个单词字母都是小写,后面的单词首字母都是大写。
2、方法需要通过参数获取元素,参数就是标签的id属性,必须写在引号内,不需要写#
3、获取元素,一定要在HTML元素位置后面,HTML有加载顺序,获取元素时,元素必须已经找到
4、id不能重复,页面中如果设置表单元素的name属性,也不能与id同名,如果重复,只会选择第一个出现。
注意代码书写位置,现在要用JS得到oBox元素,所以JS代码就要写在HTML标签后面,这样浏览器先渲染HTML节点,然后再执行到JS,否则会报错找不到元素。
<script type="text/javascript"> //获取HTML标签元素 var oBox = document.getElementById("box"); oBox.onclick = function(){ oBox.style.backgroundColor = "skyblue"; } </script> <body> <div id="box"></div> </body> |
如果页面上没有匹配id的HTML元素,将返回null,null就是空对象。
通过id获得的元素数据类型:
console.log(typeof oBox); //object |
获取的元素是对象数据类型。
IE7及低版本有一个怪癖,表单元素name属性也会被当做id,为了避免这个问题,所以页面上的name不要和id同名。
<input type="text" name="oInput" value="默认文本">
var oInput = document.getElementById("oInput");
oInput.value = "被js改了";
IE6、7都会把name当做id。
2.3操作HTML(内容和属性)
更多的是操作HTML标签属性,JS可以操作HTML任何属性,比如:src、href、title、style等
操作方法:获取标签属性,更改标签属性。
2.3.1操作HTML内容
通过innerHTML属性获取和修改标签内容:
var oBox = document.getElementById("box");
console.log(oBox.innerHTML); //获取div标签的内容
console.log(oBox.innerText); //获取div标签的文本内容
oBox.innerHTML = "通JS修改标签内容"; //通过=号给oBox对象赋值
2.3.2操作HTML属性
得到一个元素后,直接打点调用它的属性名,就能对HTML相应的属性进行修改。(有什么就点什么)
第一种:“点”语法,获取和更改,都是同元素打点调用。
//获取img标签元素
var oImg = document.getElementById("timg");
//获取标签属性的值
console.log(oImg.src);
console.log(oImg.alt);
console.log(oImg.title);
console.log(oImg.id);
console.log(oImg.width);
//设置标签属性的值,和变量赋值一样
oImg.src = "images/2.jpg";
oImg.alt = "赵丽颖是大圆脸";
oImg.title = "赵丽颖还是吃货";
class属性,要换成className,因为class是JS的保留字,不能用。
console.log(oImg.className); //获取class类名 oImg.className = "abc"; //设置class类名 |
不仅是class属性要用className这种方式避讳一下,还有以下几个属性:
class 要写成className for 要写成htmlFor rowspan 写成rowSpan colspan 写成colSpan |
第二种:通过以下两个方法获取和设置,需要用元素打点调用方法:
getAttribute() 获取标签元素的属性 setAttribute() 设置标签元素的属性 |
//获取标签属性的第二种方法:
var oImg = document.getElementById("timg");
console.log(oImg.getAttribute('src')); //获取图片src属性的路径
oImg.setAttribute('src','images/2.jpg'); //设置图片src属性的路径
getAttribute()、setAttribute()和“点”语法的区别。
第一:所有自定义属性,都不能通过点语法设置
console.log(oImg.data); //undefined自定义属性,不是w3c的属性,所以不能打点调用 console.log(oImg.getAttribute('data')); //自定义属性用getAttribute()方法可以得到 oImg.setAttribute('data','不知道写什么');//自定义属性用setAttribute()方法可以设置 |
第二:所有行内样式,点语法.style得到一个样式对象,我们可以通过.style.background继续得到小样式,但是getAttribute()得到的是字符串。
console.log(oBox.style.background);
console.log(oBox.getAttribute("style"));
console.log(typeof oBox.style); //object
console.log(typeof oBox.getAttribute("style")); //String
第三:getAttribute()、setAttribute()设置和获取class等属性不需要避讳,直接写属性名:
console.log(typeof oBox.getAttribute("class")); typeof oBox.setAttribute("class","box"); //String |
点语法效率高于getAttribute()、setAttribute()
所以,如果要获取自定义属性或操作对象,会用到,除此之外都用点语法。
2.4操作CSS样式
通过给元素对象使用“点”语法调用style属性,得到的是一个所有行内样式组成的样式对象。可以继续去打点调用css样式的属性。
通过点语法调用style属性,调用的和设置的都是行内样式。
var oBox = document.getElementById("box");
console.log(oBox.style); //获取当前div的css样式集合
oBox.style.color = "red"; //设置文字颜色
oBox.style.backgroundColor = "skyblue"; //获取当前div的css样式集合
oBox.style.width = "200px";
oBox.style.height = "200px";
oBox.style.lineHeight = "200px";
oBox.style.textAlign = "center";
oBox.style.marginLeft = "100px";
设置时,添加的新样式都是添加在行内:
获取CSS属性:如果单一属性直接写点语法调用对应的属性名,如果是复合属性,必须用驼峰命名法:
1 font- line- background- padding- margin- border- 等等都要转为驼峰命名法 |
正确写法:
1 oBox.style.backgroundColor = "skyblue"; |
错误写法:
1 oBox.style.background-color = "skyblue"; |
三、事件监听
JavaScript制作交互效果,离不开事件,所谓的事件就是用户的某个行为,能够触发一个函数的执行。
今天只学DOM标准中的0级绑定事件方法。
绑定事件监听方法:如果给一个元素添加某个事件,事件就有自己要执行的事件函数。
事件的定义:当什么时候做什么事情 事件的作用:可以捕获用户的行为 |
事件分为三要素:
事件源:就是这个事件的源头 事件类型:指的是事件什么时候发生(点击、触摸等) 执行指令:匿名函数function(){} |
中文语法解释:
事件源.事件类型 = function(){ } |
语法:
var oBox = document.getElementById('box');
oBox.onclick = function(){
alert("点击事件执行"); //这里的代码要被点击才执行,否则永远不会被触发
}
DOM0级规范的事件类型:
onclick 鼠标单击事件 ondblclick 鼠标双击事件 onmouseover 鼠标移入事件 onmouseout 鼠标移出事件 onmouseenter 鼠标移入事件 onmouseleave 鼠标移出事件 onmousedown 鼠标按下不松手事件 onmouseup 鼠标抬起事件 onmousemove 鼠标移动事件 onfocus 获取焦点事件 onblur 失去焦点事件 onkeydown 键盘按下事件 onkeyup 键盘松开事件 onchange 当元素的值发生变化时触发 onresize 窗口或框架被重新调整大小。 onselect 标签的文本被选中 onload 加载事件(某个对象加载完后,触发的事件) |
所有事件都要被触发才执行,否则匿名函数中的代表永远都不会生效。
onload加载事件:给元素添加一个加载事件时,代码只要执行到这个位置,立即添加事件监听,直到浏览器的元素加载完后,才触发onload事件,不需要用户的行为参与,它是浏览器自己的加载事件。
window.onload = function(){
//这里的代码是当浏览器加载完HTML和CSS才回头执行代码
var oBox = document.getElementById("box");
oBox.onclick = function(){
oBox.style.backgroundColor = "skyblue";
}
}
window对象的加载事件,触发条件:所有的HTML和CSS加载完后,才触发
特殊用途:帮我们实现事件函数内部的语句需要在HTML结构加载完后,才执行JS代码。
window 表示浏览器窗口 onload 表示加载后的事件 |
总结:其实就是整个页面都加载完后才执行JS代码,就是执行了一个页面加载完成后的事件。
前端笔记之JavaScript(七)深入函数&DOM那点事的更多相关文章
- 前端笔记之JavaScript(一)初识JavaScript
一.JavaScript简介 1.1网页分层 web前端一共分三层: 结构层 HTML : 负责搭建页面结构 样式层 CSS : 负责页面的美观 行为层 JavaSc ...
- 前端笔记之JavaScript面向对象(一)Object&函数上下文&构造函数&原型链
一.对象(Object) 1.1 认识对象 对象在JS中狭义对象.广义对象两种. 广义:相当于宏观概念,是狭义内容的升华,高度的提升,范围的拓展.狭义:相当于微观概念,什么是“狭”?因为内容狭隘具体, ...
- 前端笔记之JavaScript(十)深入JavaScript节点&DOM&事件
一.DOM JavaScript语言核心.变量的定义.变量的类型.运算符.表达式.函数.if语句.for循环.算法等等.这些东西都属于语言核心,下次继续学习语言核心就是面向对象了.JavaScript ...
- 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply
一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...
- 前端笔记之JavaScript(四)关于函数、作用域、闭包那点事
一.自定义函数function 函数就是功能.方法的封装.函数能够帮我们封装一段程序代码,这一段代码会具备某一项功能,函数在执行时,封装的这一段代码都会执行一次,实现某种功能.而且,函数可以多次调用. ...
- 前端笔记之JavaScript面向对象(三)初识ES6&underscore.js&EChart.js&设计模式&贪吃蛇开发
一.ES6语法 ES6中对数组新增了几个函数:map().filter().reduce() ES5新增的forEach(). 都是一些语法糖. 1.1 forEach()遍历数组 forEach() ...
- 前端笔记之JavaScript面向对象(二)内置构造函数&相关方法|属性|运算符&继承&面向对象
一.复习 1.1复习上下文 函数的调用方式 上下文 fun() window obj.fun() obj box.onclick = fun box setInterval(fun,1000) set ...
- 3.前端笔记之JavaScript基础
作者:刘耀 部分内容参考一下链接 参考: http://www.cnblogs.com/wupeiqi/articles/5369773.html http://javascript.ruanyife ...
- 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战
一.组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML.CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成. ...
随机推荐
- 勾勾街:一个专业的苹果ios app 自助打包的网站,免越狱,免证书签名
众所周知,苹果的APP开发是需要基于MAC环境的,而我们很多的开发者并没有这样的条件,如果单单为发布一款app就去买一台价格昂贵的MAC那成本就太高了! 就算你有一台MAC,也有能力自己开发出一款基于 ...
- Bphero-UWB 基站0 和 电脑串口数据格式定义
基站0 通过串口将系统中测得的距离信息发送到电脑,电脑定位软件通过三边定位算法计算出TAG的坐标,基站0 和 定位软件之间的数据格式定义如下(对官方数据结构进行了简化) 更多UWB定位信息请参阅论坛b ...
- BZOJ2567 : 篱笆
设第$i$个区间的左端点为$a[i]$,区间长度为$len$,要覆盖的部分的长度为$all$,因为区间左端点递增,所以最优方案中它们的位置仍然递增. 对于链的情况,要满足三个条件: 1. 区间$i$可 ...
- AGC001F - Wide Swap
Description 给你一个长度为$n$的排列,每次可以交换$|i-j|\geq K$并且$|a_i-a_j|=1$的数对,问你经过若干次变换后最小字典序的排列是啥 Solution 对$a$做一 ...
- SDN网络中hypervisor带来的控制器时延(Hypervisor位置的优化)
一,问题背景 1.介绍监督器大部分由软件实现,可灵活放置,高效的SDN网络虚拟化需要复杂的技术来放置hypervisor在合适的位置,才能提供租户最佳的性能.称为k-Network Hyperviso ...
- js将一个具有相同键值对的一维数组转换成二维数组
这两天,一个前端朋友在面试的笔试过程中遇到了一道类似于"用js实现将一个具有相同code值的一维数组转换成相同code值在一起的二维数组"的题目.他面试过后,把这个问题抛给了我,问 ...
- 使用Axis2创建一个简单的WebService服务
使用过Java进行过WebService开发都会听过或者接触过Apache Axis2,Axis2框架是应用最广泛的WebService框架之一了. 这里使用Axis2来开发和部署一个最简单的WebS ...
- SVN搭建外网远程访问
准备条件 SVN服务器安装及配置 SVN服务端,客户端安装配置可以参考:http://www.cnblogs.com/mq0036/p/5250198.html 花生壳客户端下载,安装,注册(内网穿透 ...
- grafana--邮箱告警配置
安装 wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-6.0.2-1.x86_64.rpm yum l ...
- 数组的初始化&缩窄转换
1.初始化: 初始化就是在声明变量的同时给变量赋值,而不是声明后再赋值. 先声明,后赋值: int a; //先声明,由于没有初始化,所以当前a的值是变量a创建前,相应的内存单元中保留的值,是未知的 ...