js中的函数-下
作用域(理解)
全局变量
在函数/方法外部声明的变量
没有加var关键字声明的变量(隐式全局变量)
局部变量
函数/方法内部,使用var声明的变量
区别:
1、全局变量就是在任何地方都可以使用的变量
2、局部变量就是只能在函数内部使用的变量
例1:创建一个局部变量
function fn(){
var a = 1;
}
console.log(a); //报错:a is not defined
在函数内部定义的变量,该变量的作用域是整个函数体,在函数体外不可引用该变量,这是局部作用域
例2: 创建一个全局变量
// 全局变量 可以在局部使用
var str='夜宵想吃啥?';
function fn1(){
// 函数内部,使用全局变量
console.log(str)
}
fn1();
不在任何函数内定义的变量就具有全局作用域。全局变量在任何地方都能调用。
变量声明周期
1.永远存在----全局变量
程序没关,一直占用内存,少用全局
2.朝生暮死----局部变量
函数的大括号开头到函数的大括号结尾
<script>
var num1 = 1; // 创建一个全局变量
num2 = 2; // 相当于 var num2 = 2; 没加var是隐式全局变量
// 创建一个函数/方法
function test1()
{
var num3 = 3; // 创建一个局部变量
num4 = 4; // 没加var是隐式全局变量
console.log(num1); // 输出全部变量num1
console.log(num2); // 输出隐式全局变量num2
console.log(num3); // 输出局部变量num3
console.log(num4); // 输出隐式全局变量num4
}
// 调用自定义函数
test1();
console.log(num1 + '-');// 输出全部变量num1
console.log(num2 + '-'); // 输出隐式变量num1
// console.log(num3); // 在函数体外部输出局部变量
console.log(num4 + '-'); // 输出函数体内局部变量
</script>
总结:
全局变量: 从js代码开始,声明,代码结束销毁.
局部变量:函数或方法开始声明,结束时变量销毁.
为什么不全部用全局变量?
1 变量污染,过多的变量名被占用
2 占用内存,浪费空间
具体的使用中
如果这个变量仅仅在函数内部有用,就声明为局部变量
JS的编译和执行(理解)
<font color="red" >JS是一段一段执行的(以''<script>''标签来分割),执行每一段之前,都有一个“预编译”.预编译干的活是:声明所有var变量(初始为undefined),解析定义式函数语句。</font>
写不写var的区别(了解)
a = 1相当于window.a = 1,是动态地为window添加一个成员;
var a = 1是在当前作用域(也就是window)下声明一个a,这个声明是在整个作用域内都有效的。
换句话说,其实区别就在于var a = 1比a = 1多了一个声明的行为。
js的执行步骤解析
1.验证变量的执行顺序
alert(t);
alert('ok');
t = 2;
t未声明,执行报错
alert(t);
alert('ok');
var t = 2;
弹出undefined和ok。预编译的时候,声明了变量t;
执行到alert(t)这行代码的时候,t尚未被赋值,所以弹出undefined。
- 函数的调用可以放在函数的声明上面
a();
function a() {}
alert('ok');
弹出ok。预编译的时候,解析了定义式函数语句function a() {},顺利执行。
4.如果是匿名函数就必须先声明,再调用
a();
var a = function() {};
alert('ok');
a不是函数,执行报错。预编译的时候,声明了变量a = undefined;执行到a()时,a还等于undefined,不是函数,所以执行a()会报错。
5.js段之间,互相的步不影响
<script type="text/javascript">
a();
alert('first block');
</script>
<script type="text/javascript">
alert('second block');
</script>
弹出second block。因为JS是一段一段执行的,第一段执行到a()的时候报错,整个第一段都不会再执行,第二段正常执行。
变量的查找规则:
- 函数内部可以使用函数外部的变量
- 有局部变量就用局部变量,没有局部变量就用全局变量。
例1: 局部变量覆盖全局变量
var num = 11;
function fn() {
var num = 22;
console.log(num);//22
}
fn();
console.log(num);//11
变量的提升
1 变量可以被移到作用域的最前面.
2 在正式声明一个函数或者变量之前就能够使用它.
变量提升的意思是变量和函数的声明会在物理层移动到作用域的最前面,变量提升实际的实现方式是JavaScript的变量和函数的声明会在编译阶段放入内存。这意味着使用者在正式声明一个函数或者变量之前就能够使用它。
例:证明变量的提升
console.log(a);
var a = '哈哈';
结果:应该是报错但输出undefined.
解释: var a = "哈哈" 定义一个变量,js中分成两步.
1 var a 发生在编译阶段, a = '哈哈'发生在执行阶段.
2 var a会被提升到当前作用域的最前面, a = 'ghostwu'留在原地等待执行阶段
a = '哈哈';
var a;
console.log( a );
//上面这段代码经过编译之后,变成下面这样
var a; //被提升到当前作用域的最前面
a = 'ghostwu'; //留在原地,等待执行
console.log( a ); //输出ghostwu
例:函数的提升
因为函数表达式和函数的声明,在编译阶段,会产生不同的解释效果,所以函数的声明会被提升,案例见下面代码
show();
function show(){
console.log( a );
var a = 'ghostwu';
}
//函数声明会被提升,所以上面的代码经过编译之后,就变成下面这样
function show(){ //函数声明被提升到 当前作用域的最前面
var a;
//var声明被提升到当前作用域的最前面, 注意,他不会提升到函数的外面, 因为当前的作用域是在函数中
console.log( a );
a = 'ghostwu';
}
show();//输出undefined
但是 函数表达式 ( 匿名函数 )是不会被提升的,看下面的例子:
fn(); //报错,fn is not a function
// 匿名函数的提升
fn();
var fn = function(){
}
/*
执行过程:
var fn;
fn();
fn=function(){}
*/
总结:
知道编译和执行以及变量的提升,就是为了了解js内部执行的顺序,规避一些常见的错误.
递归函数(了解)
所谓的递归函数就是在函数体内调用本函数。使用递归函数一定要注意,处理不当就会进入死循环。
递归函数一定要有终止条件,否则便是死循环
例1:使用递归求1+2+3+4+5的和
function fn(n){
if(n<=1){
return 0;
}else{
var sum = n+fn(n-1);
return sum;
}
}
console.log(fn(5));
观察结构:
执行步骤
第一步:5+fn(4)
fn(4)是什么呢? 就是 4+fn(3)
fn(3)是什么呢? 3+fn(2)
…..
当n<=1时,return 1 这个return 是fn(1) 这个函数的。
例2:使用递归求出5的阶乘
// 阶乘
// n!
// 5*4*3*2*1
function fn(n){
if(n == 1){
return 1;
}else{
return n * fn(n-1);
}
}
console.log(fn(6))
事件 函数(重要)
作用介绍
事件:以“on”开头的都是事件,每个事件后面都有“事件处理”,事件处理一般是由函数来担当。
主要用于和用户产生一定的交互,提高页面或程序的交互性。
事件和函数之间的关系
事件和函数之间的关系
当触发事件的时候,执行函数-------按下制冷按钮,空调吹冷风
事件----调用----函数
常见鼠标的事件
onclick 鼠标单击
ondblclick 鼠标双击(必须连续点击两下)
onmouseover 鼠标移入,即鼠标停留在图片(元素)等的上方(一次)
onmouseout 鼠标移出,即离开(元素)图片等所在的区域(一次)
onmousemove 鼠标移动,即鼠标在(元素)图片的上方不断移动(多次)
onmouseup 事件会在鼠标按键被松开时发生。
onmousedown 事件会在鼠标按键被按下时发生。
表单事件
onblur 指定元素失去焦点(光标没了)
onfocus 指定元素获取焦点(点击出现光标)
onreset 重置表单的时候触发事件,执行对应的js功能
onsubmit 提交表单的时候触发事件,执行对应的js功能
onchange 下拉菜单改变时候触发
所有事件在这里:
http://www.w3school.com.cn/jsref/dom_obj_event.asp
例1: 在div中绑定onclick事件,点击之后弹出框
<body>
<div onclick="fn()">弹出事件</div>
<script>
function fn(){
alert(454411);
}
</script>
</body>
例2:鼠标移入的时候弹出onmouseover (事件的绑定方式)
方法1:
<img src="./pao.jpg" id="img" onmouseover ='changeImg()' alt="">
<script>
// 鼠标移入图片,更换图片
// 鼠标移入事件 onmouseover
function changeImg(){
// 根据id获取图片的节点
var imgObj = document.getElementById('img');
//console.log(imgObj)
// 更换图片的地址
imgObj.src = './hai.jpg';
}
</script>
方法2:扩展:根据标签名称获取标签
<body>
<img src="1.png" alt="" />
</body>
</html>
<script>
//根据标签名 查找页面元素
var oImg = document.getElementsByTagName("img")[0];
//鼠标移入到图片上 改变图片的路径 换图
oImg.onmouseover = function(){
oImg.src = "goods.jpg";
}
//鼠标离开 还原图片
oImg.onmouseout = function(){
oImg.src = "1.png";
}
</script>
例3:输入框发生改变时,输出内容
<p>
<label for="name">用户名:</label>
<input type="text" id="fname" onchange="change()" value=""/>
</p>
<script type="text/javascript">
function change(){
alert('你在修改内容');
}
</script>
</body>
</html>
例4:鼠标按下与松开的事件
<p onmousedown = "down()" onmouseup="up()" >假如上苍不够慷慨,降我们以普通的生,何必要无谓的抱怨.又何必报之以猥琐的活</p>
<script>
// 鼠标按下触发
function down(){
console.log('我们总要走向远方');
// 改变p标签背景颜色
var pObj = document.querySelector('p');
pObj.style.color = 'red';
}
// 鼠标弹起时触发
function up(){
console.log('吟的一手好湿');
var pObj = document.querySelector('p');
pObj.style.color = 'green';
}
</script>
例5:焦点事件的使用(只有表单元素才有)
用户名:<input onfocus="changeColor()" onblur="goFn()" type="text" id="user" value="" />
<script>
// 获取焦点 onfocus
// 失去焦点 onblur
function changeColor(){
var inputObj = document.querySelector('input');
// 更改输入框的颜色
inputObj.style.background='green';
}
// 失去焦点的事件
function goFn(){
alert('么妹,你要走了???')
}
多学一招:使用鼠标移入事件,操作样式:
<st<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div{
width:200px;
height: 200px;
background: green;
}
</style>
</head>
<body>
<div onmouseover="changeSize()" onmouseout="restSize()"></div>
<script>
function changeSize(){
var divObj = document.querySelector('div');
// 在js中给标签设置样式,都是行内样式,必须使用style
// alert('妹妹,我来了')
divObj.style.width='400px';
divObj.style.height='400px';
divObj.style.background = 'red';
}
// 鼠标移走事件,移出之后图像还原
function restSize(){
//alert('妹妹,我走了')
var divObj = document.querySelector('div');
divObj.style.width='200px';
divObj.style.height='200px';
divObj.style.background = 'green';
}
</script>
</body>
</html>yle>
div{
width:100px;
height:100px;
background :red;
}
</style>
<body>
<div></div>
</body>
</html>
<script>
// 小目标:鼠标移入时,更改宽度
// 1 获取节点
var divObj = document.getElementById('xiao');
// 2 给div节点绑定移入事件
divObj.onmouseover = function(){
// 3 修改div的width,使用.style操作样式属性
/// alert(1233);
divObj.style.width =400+'px';
}
</script>
事件的绑定方式
第一种:行内绑定
<input type="text" name="" value="" onfocus="fn2()" id="">
第二种:js绑定
// 1 获取节点
var divObj = document.getElementById('xiao');
// 2 给div节点绑定移入事件
divObj.onmouseover = function(){}
构造函数及对象类型(了解)
万物都是对象.
var str = "123”; //字面量方式生成
console.log(str); //123
console.log(typeof str); //string
var str = new String("123”); //构造函数方式生成
console.log(str); //String {"123"}
console.log(typeof str); //object
构造函数只会产生对象,构造函数是用来构造对象的函数
构造函数用来构造对象,对象被用来编程,面向对象向编程
new关键字,用来执行函数,得到当前执行函数的同名对象
但是,当new系统的类型函数时,得到的是对应的数据类型,但是typeof出来的都是object
使用Number()的构造函数方式,创建数字
var n = 1;
console.log(n + 1);
var n2 = new Number(1);
var n3 = new Number(1);
console.log(typeof n2)
console.log(n2)
console.log(n2 + 1)
对象,被new出来的都是对象
任何两个对象都不相等
对象的属性值,可以是任何数据
当对象的属性值是非函数时,称这个属性叫属性
当对象的属性是函数时,称这个属性叫方法
对象的组成(本质):键值对
每组键值对之间用,隔开
每个键和值之间用:连接
对象的作用:存储数据;用来编程
读取对象的信息:对象名.属性名
对象的声明(了解)
<script>
//对象的声明
// 对象中:只有方法和属性
// 方法就是函数,属性就是变量,
// 属性之间使用,隔开
// 属性是以键值对的形式存在 key:value
//重要:对象的形式以{}存在
var friend={
name:'毛毛',// 键值对
age:22,
say:function(){ // 方法,以匿名函数的形式声明
alert('来,来,你见过我的美吗?')
}
}
//对象中属性调用
// 对象名.属性名
console.log(friend.name)
//调用方法: 对象名.方法名()
friend.say();
</script>
Math对象调用其中的方法
Math.random()
Math.round()
num.toString()
num.toFixed()
arguments.length
js的顶层对象window
所有全局的内容全部属于window对象的属性
window在使用过程中可以省略
window是一个对象,所以可以使用点(.)语法操作属性
console.log(typeof window)
console.log(window)
window.alert(1)
var a = "qianfeng";
console.log(window.a)
window.a = "heiheiheiehieh"
console.log(window.a)
console.log(a)
function abc(){
console.log("hahahahah")
}
window.abc()
综合练习(有基础的尝试)
例1: 验证卡号,是不是以指定的10开头,是否为指定的8位
<script type="text/javascript">
function fun_focus(){ //得到焦点
if(frm.card.value=='请注意格式:10XXXXXX')
frm.card.value='';
}
function fun_blur(){ //失去焦点
if(frm.card.value=='')
frm.card.value='请注意格式:10XXXXXX';
else{ //判断输入值的格式是否正确
var card=frm.card.value;
if(card.length!=8){ //卡号不是8位
alert('卡号是8位的,你输入的是'+card.length+'位');
}else{
if(card.substr(0,2)!='10'){
alert('卡号必须是"10"开头');
}else{
alert('卡号正确');
}
}
}
}
</script>
<form name='frm' action="">
卡号:<input type="text" name="card" value='请注意格式:10XXXXXX' onfocus='fun_focus()' onblur='fun_blur()'>
</form>