一、作用域
1. 定义:能起到作用的区域就叫做作用域。定义在不同区域的变量,他的作用域是不一样的。
2. 作用域:
(1)全局作用域:整个网页。
(2)局部作用域:某个函数内部的区域
3. 变量:
(1)全局变量:定义在函数外的变量 ----- 作用域 - 整个网页
(2)局部变量:定义在函数内的变量 ----- 作用域 - 函数内部
4. 局部可以访问到全局的变量,全局访问不到局部的变量
5. 如果全局和局部都有同名的变量,局部输出时如何输出呢?
变量在输出时,首先考虑当前作用域,当前作用域中就会输出当前作用域中的变量,如果
当前作用域中没有,才会考虑外面的全局。
//全局变量
var a = 10;
function fn(){
console.log(a);
}
fn()
//局部变量
function fn(){
var a;
}
console.log(fn())
二、作用域链
1.含义
作用域链:由作用域嵌套形成的一条链式结构
2.规则
(1)当我们将一个变量当做是一个 具体的数据 去使用时,先在当前定义域中查找看有没有定义过这个变量,如果有定义过,直接使用,如果当前定义域中没有定义过,那就向上一级定义域进行查找,...直到全局,找到了就使用,如果全局也没有定义过,就报错
function fn1(){
function fn2(){
function fn3(){
var b = 2
var c = a + 1 //--------此时 a为具体的数据,所以系统不会给a定义变量
console.log(a);
}
fn3()
console.log(b);
}
fn2()
}
fn1()
(2)当我们给一个变量空间赋值的时候,现在当前定义域找是否定义过这个变量,如果定义过:复制成功,修改的是当前定义域中的这个变量,如果没有定义过:就去上级作用域中查找....直到全局,如果全局找到了,就是在给全局变量赋值,如果全局也没找到,那就会在全局定义这个变量并赋值
var a = 1
function fn1(){
var a = 3
function fn2(){
a = 2
}
fn2()
}
fn1()
console.log(a)
3.预解析练习题
//注意预解析
//第一题
var num = 10;
fn1();
function fn1() {
console.log(num);
var num = 20;
}
//第二题
var a = 18;
fn2();
function fn2() {
var b = 9;
console.log(a);
console.log(b);
}
//第三题
fn3(); //输出 a=9; var b=9; var c=9;
console.log(c);
console.log(b);
console.log(a); //外部没有定义a,只定义了b,c
function fn3() {
var a = b = c = 9;
console.log(a);
console.log(b); //内部函数没有定义b,向上查找,外部也咩有定义b,然后系统会自动定义b
console.log(c);
}
//第四题
var a = 4;
console.log(a);
a = 6;
console.log(a);
function a() {
console.log('哈');
}
a();
a = 10;
console.log(a);
//第五题
//当 变量a 遇到 函数a时,变量a会被函数a覆盖
function fn(a) {
console.log('我是 fn 函数')
a()
function a() {
console.log('我是函数 a')
}
}
fn(10)
//第五题预解析过程
function fn(a) {
a = 10//------此时,系统给a已经定义为变量了, 首先: 外部给a变量一个值 ,所以要先把10代入a
console.log('我是 fn 函数')
a()
function a() { //------此时,变量a已经有空间了 ,然后函数也给 a一个空间 , 其次: 函数又
//---------给a 一个空间具体的值,所以函数a具体数据 把变量a空间 覆盖了
console.log('我是函数 a')
}
}
fn(10)
三、递归函数
1.含义:在函数内部调用自己
2.语法:
function fn(){
fn()
}
fn()
3.练习题
//计算一个数字以内的累加
function fn(n){
if(n===1){
return 1;
}
n = n + (fn(n-1))
return n
}
console.log(fn(5));
//求阶乘
function fn(n){
if(n===1){
return 1
}
return n*fn(n-1)
}
console.log(fn(6))
// 求黄金分割数列 一组数字:1 1 2 3 5 8 13 21 34 55 89 ....
function fn(n){
if(n===1 || n===2){
return 1
}
return fn(n-2)+fn(n-1)
}
var sum = fn(7)
console.log(sum);
四、事件
1.含义:处理用户在网页中行为的代码
2.组成
事件通常由3个要素组成:
(1)事件源:触发事件的标签元素,例如,点击的是div、还是button 。。。
(2)事件类型:行为的类型,是单击还是双击,还是右击。。。
(3)事件处理程序:事件触发后要做的事情 - 函数
3.事件语法
2-1. 标签.on行为类型=函数代码
(1)标签:可以直接使用 标签的id名 代表在js中代表标签,注意id名不要使用js关键字
(2)类型:1.鼠标类:(1)当鼠标左键单击:click
(2)当鼠标左键双击:dblclick
(3)当光标在指定的内容上面:mouseover
(4)当光标离开指定的内容:mouseout
2.键盘类:(1)当键盘按下那一刻:keydown
(2)当键盘抬起那一刻:keyup
3.表单类:(1)当输入框获取焦点:focus
(2)当输入框失去焦点:blur
(2)当指定的标签里面内容有变化的时候:change
(2)表单提交:submit
4.window:(1)onload:网页中其他资源都加载完成后再加载这个事件中
例如: 的内容
<button id="btn">按钮</button>
<script type="text/javascript">
btn.onclick = function(){
alert("点击了按钮!");
}
</script>
(3)函数代码:1.匿名函数
2.函数名称 ------ 不要调用
2-2. 行内写法
(1)标签 on类型="js代码"
(2)标签 on类型="函数名()"
4.注意:(1)如果给事件赋值函数名,千万不能加小括号调用
(2)在行内的事件中调用函数一定要加小括号调用才行
5.js可以像css一样有3种写法:
(1)行内写法:事件
(2)内联写法:平常写的代码
(3)外联写法:项目中要将js代码放在一个文件中,在html中引入js文件
<script src="js文件路径"></script>
五、对象
1.概念
(1)复杂的数据 - 一个空间中存储多个数据
(2)对象有一个特性,第一次打开的时候,只能看到Object,再次刷新页面, 会显示里面的数据
2.定义
(1)var obj = {}
键和值之间使用冒号隔开,键值对之间使用逗号隔开
(2)var obj = new Object()
(3)定义有数据的对象
var obj = {
key1: value1,
key2: value1,
...
}
(3-1)键值对的组成
键 - 本质是字符串
一般不加引号;当键中包含连字符的时候,就必须加引号
值 - 什么类型都可以
(4)对象中键值对的数量没有限制,可以有任意多个
(5)对象中的键都是字符串,只是正常情况下可以省略引号,但如果键中包含连字符,就不能省略引号了
var obj = {
"name":"张三",
age:12,
height:180,
"province-name":"山东省"
};
console.log(obj);
从输出的结果中能看到,书写顺序和显示的顺序是不同的,因为对象中的键值对是没有顺序的。
六、对象的基本操作
(1)访问
(1-1)对象.属性名
console.log( obj.name );
(1-2)对象['属性名']
console.log( obj[f] );
(2)设置
(1-1)对象.属性名 = 值
obj.name = '李四'
(1-2)对象['属性名'] = 值
obj['age'] = 12
注意:
遍历对象时,输出对象中的值,必须使用对象[代表键的变量]
这种形式来输出 ,因为 . 的语法有歧义; 浏览器会将obj.f
识别为:我们正在访问obj中键为f的值
.
后面的内容,表示对象中的键的名称,所以此时只能使用[]
的形式来访问
obj[f] = '女'
对象中的键是唯一的:设置的属性在对象中存在了-------修改值
设置的属性名在对象中还不存在-------新增键值对
(3)删除
1-1.delete 对象.属性名
delete obj.sex
1-2.delete 对象['属性名']
delete obj['name']
(4)方法概念
对象中值的类型是没有限制的,可以是任意类型。当值不是函数的时候,我们将这
个键值对叫做对象的属性,当值是一个函数的时候,我们将这个键值对叫做对象的方法。
方法的访问和属性是一样的
七、对象的遍历
(1)将对象中的每个键值对都经历一次
(2)for(var 变量 in 对象) {
变量 - 代表每一个对象中的属性名
}
var obj = {
name: '张三',
age: 12,
sex: '男'
}
for(var key in obj) {
console.log(key); // 输出每一个键
console.log( obj[key] ); // 输出每一个值
console.log(key + '===' + obj[key]); // 把键和值用等号连接起来
}
八、将对象转成字符串
var obj = {
username: 'cuihua',
password: '123456',
email: '123456@qq.com'
}
// 转成字符串: 'username=cuihua&password=123456&email=123456@qq.com'
var str = '' // 容器
var s = ''
for(var key in obj) {
str = str + '&' + key + '=' + obj[key]
}
console.log(str);
九、统计字符串中字符出现的个数
// 统计每个字符出现的个数
var str = 'abaabcdd'
/*要求结果:以对象形式来统计
{
a: 3,
b: 2,
c: 1,
d: 2
}
*/
var obj = {} // 以对象形式输出
for (var s = 0; s < str.length; s++) {
console.log(str[s]); // 字符串中每个字符
// 将每个字符都作为对象的属性
if (obj[str[s]] >= 1) { // 如果obj['a']里面有值,一定大于等于1个,因
// 为else已经给obj[str[s]]赋值为 1了,此处1指的是个数
obj[str[s]] = obj[str[s]] + 1
} else {
obj[str[s]] = 1 // str[s] - 理解为是一个变量,赋值为1个
}
/* 帮助理解:
obj['a'] = 1 + 1 + 1
obj['b'] = 1 + 1
obj['c'] = 1
obj['d'] = 1 + 1
*/
}
console.log(obj);