一、函数的深入
(一)、作用域
1.作用域
所谓的作用域,值得是:一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
作用域有两种,一种是全局作用域,一种是局部作用域。(这里讲的ES5版本的语法,后面学习到ES6语法的时候,就不一样了。)
2.全局作用域
- 作用于,整个代码的执行环境。整个script标签里面,或者一个独立的js文件。
3.局部作用域(函数作用域)
- 是相对于全局来说的,函数内部才启下效果,
4.注意一下js没有块级作用域,
- 块作用域由{}包括起来。
- 比如java中的块作用域,(当然了,如果你学习过java的前提下,你可以比较容易理解)。不理解就无所谓了。可以略过
- 以上说的是ES6之前,ES6之后的变化比较大。
5.变量的作用域
- 变量的作用域有两种,
- 全局变量
- 局部变量
- 全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
- 全局变量在代码的任何位置都可以使用
- 在全局作用域下 var 声明的变量 是全局变量
- 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用),容易混淆
- 局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部 var 声明的变量是局部变量
- 函数的形参实际上就是局部变量
- 区别:
- 从内存角度来分析,只有浏览器关闭的时候才销毁,比较占内存,局部变量是函数运算完之后就销毁,比较省内存
- 作用域链
这个知识点比较重要,
- 简单的来说,首先我们的函数哈,有一个特性,就是内部函数可以访问外部函数的变量,函数中还有函数,那么又可以产生一个作用域下的另一个作用域。作用域链指的是,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
作用域链:采取就近原则的方式来查找变量最终的值。
var a = 1;
function fn1() {
var a = 2;
var b = \'22\';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 ? -
console.log(b); //b的值 ?
}
}
}
fn1();
(二)、预处理
1.预处理就是什么?
js在浏览器中由js解析器来执行,js解析器解析js的时候有两步,1.预解析,2.执行代码
- 所谓的预解析指的是:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
预解析会把变量和函数的声明在代码执行之前执行完成。
2. 变量的预解析是?
所谓的变量预解析,也叫作 变量或者函数的提升:变量的声明会提升到当前作用域的最上面,注意的是变量的赋值不会提升
console.log(num); // 结果是多少?---这个值是undefined
var num = 10; // ?
3.函数的预解析
和变量预解析类似,函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
console.log(fun)
fun();
function fun() {
console.log("打印机")
}
//以下代码会报错
fun();
var fun = function fun() {
console.log("打印机")
}
- 函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!加一个括号,就表示调用它了
(三)、对象
1. 对象是什么?
独享是一组无序的相关属性和方法的集合,所有的事务都是一个对象,对象由属性和方法构成,举一个简单的例子,
大黄,是我养的一条狗,它有它的名字,它有它的年龄5岁,它有它的性别,公的。这些都是它的属性,它有一些功能,比如和我玩,摇尾巴,吃东西,等等。这些都是它的方法。 大黄是一个对象,它是一个具体的对象,我们还可以把它抽象出来(抽象抽象,抽出像的部分)。定义一个类,所谓的类,好比于,现在有一个狗,这个类,狗类,它也有名字,年龄,性别等,它也有它的方法,叫,摇尾巴,吃东西等等,而我们这里的大黄,就是这个类的具体实现。
2. js中创建对象的三种方式
主要创建方式有三种,
- 用字面量来直接创建对象,简答的理解就是一个花括号{};
代码实例:
// 定义对象
var star = {
name : \'bmlaoli\',
age : 18,
sex : \'男\',
sayHi : function(){
alert(\'大家好啊~\');
}
};
// 调用对象
console.log(star.name); //输出的是bmlaoli
console.log(star.sayHi());//输出的大家好~
- 利用关键字new来创建一个对象
- 内置构造函数Object创建对象
var andy = new Object();
//给对象添加属性和方法
andy.name = \'bmlaoli\';
andy.age = 18;
andy.sex = \'男\';
andy.sayHi = function(){
alert(\'大家好啊~\');
}
/* 需要注意的地方
Object() :第一个字母大写
new Object() :需要 new 关键字
使用的格式:对象.属性 = 值;
*/
3.利用构造函数创建对象
- 什么是构造函数呢?
所谓的构造函数指的是:
是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。它与类是不同的,有区别的,
它的执行方式是:
1.立刻在堆内存中创建一个新的对象
2.将新建的对象设置为函数中的this
3.逐个执行函数中的代码
4.将新建的对象作为返回值
- 刚才我们讲到 堆内存,其实除了堆内存还有栈内存。在很多的程序设计语言中,比如java,都要栈和堆。具体的详细内容你可以参考这个博客:点击
- 构造函数的封装格式:
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
- 构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
//以上代码中,obj即接收到构造函数创建出来的对象。
- 使用构造函数需要注意的地方,
- 注意:
1. 构造函数约定**首字母大写**。
2. 函数内的属性和方法前面需要添加 **this** ,表示当前对象的属性和方法。
3. 构造函数中**不需要 return 返回结果**。
4. 当我们创建对象的时候,**必须用 new 来调用构造函数**。
- 其他:
构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化
- new关键字的作用:
1. 在构造函数代码开始执行之前,创建一个空对象;
2. 修改this的指向,把this指向创建出来的空对象;
3. 执行函数的代码
4. 在函数完成之后,返回this---即创建出来的对象
4.使用对象的最佳选择
遍历它!这在日常的工作中,项目的开发中,使用的非常的频繁!
for (变量 in 对象名字) {
// 在此执行代码
}
/*
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
*/
for (var k in obj) {
console.log(k); // 这里的 k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
(四)、常见的内置对象
小小的建议:如果你对于一些内置对象不太明白,请你直接去查文档,比看完在这里BB有用得多
相关文档的查阅地址:
查找文档:学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN/W3C来查询。
Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括 html、CSS 和万维网及 HTML5 应用的 API。
MDN