作用域
作用域表示一个代码区域,也表示一个运行环境
1. 全局作用域
在全局作用域中声明的变量,会被提升到脚本块的顶部,并且会成为全局对象的属性。
2. 函数作用域
在函数作用域中声明的变量,会被提升到函数的顶部,并且不会成为全局对象的属性.
1.1 全局作用域:任何不在函数中或是大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问
// 全局变量
var greeting = 'Hello World!';
function greet() {
console.log(greeting);
}
// 打印 'Hello World!'
greet();
1.2 函数作用域(局部作用域):如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问
function greet() {
var greeting = 'Hello World!';
console.log(greeting);
}
// 打印 'Hello World!'
greet();
// 报错: Uncaught ReferenceError: greeting is not defined
console.log(greeting);
可见上述代码中在函数内部声明的变量或函数,在函数外部是无法访问的,这说明在函数内部定义的变量或者方法只是函数作用域
1.3 块级作用域:ES6引入了let和const关键字,和var关键字不同,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量
{
// 块级作用域中的变量
let greeting = 'Hello World!';
var lang = 'English';
console.log(greeting); // Prints 'Hello World!'
}
// 变量 'English'
console.log(lang);
// 报错:Uncaught ReferenceError: greeting is not defined
console.log(greeting);
递归函数
简单点来理解: 函数的递归就是 函数内部调用自己,一个递归函数可以接受两个输入参数:一个最终状态(终止递归)或一个递归状态(继续递归)。
递归概念
上文学到闭包的概念, 函数嵌套函数, 那么 递归 也同样在函数内部嵌套自己, 也相当于闭包.
再来看一下 "百度百科" 对递归的概念的描述: "程序调用自身的编程技巧称为递归(recursion)。" 也就是递归作为一种算法在前端和后端都广泛应用的. 但是递归也是有很 da 的缺点的, 应尽量避免使用...还是要学习一下
递归函数的作用
递归函数就调用自己的函数. 在某些算法中, 处理一些类似树相关的数据结构的算法, 就可以利用递归函数方便简洁地实现.
函数调用自身需要注意"栈溢出"的问题, 需要控制条件, 以免调用太多次而产生的溢出栈的问题. 递归允许以不同的样式来进行编写函数:
我们在写递归函数时需要注意内存的大小限制: 比如 函数A 调用 函数B, 函数B 调用 函数C, JavaScript 解释器需要记住这个三个函数的执行上下文:当最内部 函数 C 执行完后, 需要知道在哪里恢复函数 B, 同理 函数 B 执行完成后, 函数 A 的恢复也需要清楚.
js
复制代码
function 函数A() {
function 函数B() {
function 函数C() {}
}
}
函数递归的应用
在一些数据结构中, 使用递归可以方便地帮助我们处理数据: 被用于处理包含有更小的子问题的一类问题
比如对 DOM 的操作处理: 对一个节点DOM 的子节点进行递归操作
js
复制代码
function walkTree(node) {
if (node == null) //
return;
// ... 这里省略对节点的具体操作
//
for (var i = 0; i < node.childNodes.length; i++) {
walkTree(node.childNodes[i]);
}
}
对象
1、对象基础
对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法)
一个对象由许多的成员组成,每一个成员都拥有一个名字(像上面的 name、age),和一个值(如 ['Bob', 'Smith']、32)。每一个名字/值(name/value)对被逗号分隔开,并且名字和值之间由冒号(:)分隔,语法规则如下所示:
var objectName = { member1Name : member1Value, member2Name : member2Value, member3Name : member3Value }
var person = {
name : ['Bob', 'Smith'],
age : 32,
gender : 'male',
interests : ['music', 'skiing'],
bio : function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I'm ' + this.name[0] + '.');
}
};
对象成员的值可以是任意的,在我们的 person 对象里有字符串 string,数字 number,两个数组 array,两个函数 function。前4个成员是资料项目,被称为对象的属性(property) ,后两个成员是函数,允许对象对资料做一些操作,被称为对象的方法(method)
一个如上所示的对象被称之为对象的字面量(literal) ——手动的写出对象的内容来创建一个对象。不同于从类实例化一个对象,
当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来创建一个对象,举例来说,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,而且比起数组更为易用,因为你使用名字 name 来标识这些资料。
2、点表示法
访问对象的属性和方法,当你想访问对象内部的属性或方法时,然后是一个点(.),紧接着是你想要访问的项目,标识可以是简单属性的名字(name),或者是数组属性的一个子元素,又或者是对象的方法调用。 person.age person.interests[1] person.bio()
子命名空间:可以用一个对象来做另一个对象成员的值 name : ['Bob', 'Smith'], 改成 name : { first : 'Bob', last : 'Smith' },
访问:链式的再使用一次点表示法 person.name.first person.name.last
3、括号表示法
另外一种访问属性的方式是使用括号表示法(bracket notation) person.age person.name.first
换成: person['age'] person['name']['first']
这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组(associative array)了——对象做了字符串到值的映射,而数组做的是数字到值的映射。
5、this 的含义
this 指向了代码所在的对象(其实代码运行时所在的对象)。在字面量的对象里this看起来不是很有用,但是当你动态创建一个对象(例如使用构造器)时它是非常有用的,之后你会更清楚它的用途。
事件
1、概念
js中的事件指的是用户在网页中的行为,例如:鼠标点击、鼠标移动、。。。。。。
事件通常由3个要素组成:
- 事件源:触发事件的标签元素,例如,点击的是div、还是button 。。。
- 事件类型:行为的类型,是单击还是双击,还是右击。。。
- 事件处理程序:事件触发后要做的事情 - 函数
2、语法
事件源.on事件类型 = 函数
例:
<button id="btn">按钮</button>
<script type="text/javascript">
btn.onclick = function(){
alert("点击了按钮!");
}
</script>
事件类型
| 事件 | 备注 |
|---|---|
| onclick | 当鼠标左键单击 |
| ondblclick | 当鼠标左键双击 |
| onmouseover | 当光标在指定的内容上面 |
| onmouseout | 当光标离开指定的内容 |
| onkeydown | 当键盘按下的那一刻 |
| onkeyup | 当键盘抬起的那一刻 |
| onfocus | 当输入框得到焦点 |
| onblur | 当输入框失去焦点 |
| onchange | 当指定的标签里面内容有变化的时候 |
| onsubmit | 提交事件 |
| onload | 当整个网页加载完成后 |
事件的其他写法:
// 给事件赋值函数名称
btn.onclick = fn
function fn(){
console.log('点击了按钮')
}
// 给事件赋值变量名 - 值是函数
var fn = function(){
console.log('点击了按钮')
}
注意:如果给事件赋值函数名,千万不能加小括号调用
事件还可以写在行内:
<!-- 直接在行内写js代码 -->
<button onclick="console.log('点击了按钮')">按钮</button>
<!-- 可以在行内调用函数 -->
<button onclick="fn()">按钮</button>
<script>
function fn(){
console.log('点击了按钮')
}
</script>