js基础:07、作用域(全局作用域、函数作用域)、声明提前(变量的声明提前、函数的声明提前)、执行上下文(this)、新创建对象方法、构造函数
javascript 的函数的作用域及声明提前及this及构造函数:
- Ⅰ、变量与函数的声明提前:
- 其一、代码为:
- 其二、结果为:
- Ⅱ、作用域(Scope)之全局作用域:
- 其一、代码为:
- 其二、结果为:
- Ⅲ、作用域(Scope)之函数作用域:
- 其一、代码为:
- 其二、结果为:
- Ⅳ、执行上下文(this):
- 其一、代码为:
- 其二、结果为:
- 其三、代码为:(输出调用方法对象的名字)
- 其四、结果为:
- 其五、代码为:判断this指向
- 其六、结果为:
- Ⅴ、新创建对象的方法:工厂方法创建对象
- 其一、代码为:
- 其二、结果为:
- Ⅵ、构造函数:
- 其一、代码为:
- 其二、结果为:
- Ⅶ、小结:
Ⅰ、变量与函数的声明提前:
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 变量的声明提前* - 使用 var 关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),* 但是如果声明变量时不使用 var 关键字,则变量不会被声明提前* (即:若使用 var 声明,在先输出后赋值的情况下输出为 undefined,若不使用 var 声明,在先输出后赋值的情况下会报错;)* (若使用 var 声明,在先赋值后输出的情况下输出为标准做法,若不使用 var 声明,在先赋值后输出的情况下也没问题,默认(即:本质)是 window.a 来赋值的,是省略了 window)* * * 函数的声明提前* - 使用函数声明形式创建的函数 function 函数(){}* 它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数(即:不仅是声明提前了,而是直接将该函数都创建好了,与位置无关,可以认为与 var 声明是一个层级)* 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用(即:函数变量 fun2 会被提前声明,注意是被提前声明而未被赋值,因此未赋值前输出 fun2 的值为 undefined,因此需要先赋值后调用)*/// console.log("a = "+a);// a = undefined// var a = 123;// fun();//输出结果为:我是一个fun函数(因为该方式的函数声明,会被提前)// fun2();//输出报错:08.变量的声明提前.html:29 Uncaught TypeError: fun2 is not a function //函数声明,会被提前创建function fun(){console.log("我是一个fun函数");}//函数表达式,不会被提前创建var fun2 = function(){console.log("我是fun2函数");};fun();//输出结果为:我是一个fun函数fun2();//输出结果为:我是fun2函数</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

Ⅱ、作用域(Scope)之全局作用域:
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 作用域* - 作用域指一个变量的作用的范围* * - 在 JS 中一共有两种作用域:* * 1.全局作用域* - 直接编写在 script 标签中的 JS 代码,都在全局作用域* - 全局作用域在页面打开时创建,在页面关闭时销毁* - 在全局作用域中有一个全局对象 window,* 它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用* - 在全局作用域中:* 创建的变量都会作为 window 对象的属性保存* 创建的函数都会作为 window 对象的方法保存* - 全局作用域中的变量都是全局变量,* 在页面的任意的部分都可以访问的到* * 2.函数作用域* */var a = 10;var b = 20;// var c = "hello";// console.log(window.c);//此时输出 c 与输出 window.c 的效果是一样的(即:hello);function fun(){console.log("我是fun函数");}// window.fun();//此时输出 fun() 与输出 window.fun() 的效果是一样的(即:我是fun函数);window.alert("hello");</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

Ⅲ、作用域(Scope)之函数作用域:
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 函数作用域 * - 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁* - 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的* - 在函数作用域中可以访问到全局作用域的变量* 在全局作用域中无法访问到函数作用域的变量* - 当在函数作用域中操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用* 如果没有则向上一级作用域中寻找,直到找到全局作用域,* 如果全局作用域中依然没有找到,则会报错 ReferenceError* - 在函数中要访问全局变量可以使用 window 对象*///创建一个变量var a = 10;function fun(){var a = "我是fun函数中的变量a";var b = 20;// console.log("a = "+a);// a = 我是fun函数中的变量a(会一直输出该值)function fun2(){console.log("a = "+window.a);}fun2();}// fun();// a = 10// console.log("b = "+b);// 报错:Uncaught ReferenceError: b is not defined(原因:全局作用域中没有 b 变量)/** 在函数作用域也有声明提前的特性,* 使用 var 关键字声明的变量,会在函数中所有的代码执行之前被声明(即:与全局的特性基本上一致,可以称为一个小的全局)* 函数声明也会在函数中所有的代码执行之前执行*/function fun3(){fun4();// 函数声明提前,弹窗为:I'm fun4console.log(a);// 变量声明提前,输出为:undefinedvar a = 35;function fun4(){alert("I'm fun4");}}// fun3();var c = 33;/** 在函数中,不使用 var 声明的变量都会成为全局变量*/function fun5(){console.log("c = "+c);// c = 10;//d 没有使用 var 关键字,则会设置为全局变量d = 100;//若在函数中未使用 var 声明变量则默认为用 window 声明的变量,即:window.d = 100;}// fun5();// c = 33(原因: fun5 函数中不存在 c 变量,因此输出的 c 是全局变量的结果)//在全局输出 d// console.log("d = "+d);// d = 100(注意:需要在 fun5 运行后,且 d 变量并没有使用 var 声明后,此时的 d 变量是全局变量)var e = 23;/** 定义形参就相当于在函数作用域中声明了变量*/function fun6(e){alert(e);}fun6();// 弹窗输出结果为:undefined(原因:形参没有被赋值,默认输出就是 undefined)</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

Ⅳ、执行上下文(this):
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 解析器在调用函数每次都会向函数内部传递进一个隐含的参数,* 这个隐含的参数就是 this,this 指向的是一个对象,* 这个对象我们称为函数执行的 上下文对象,* 根据函数的调用方式的不同,this 会指向不同的对象* 1.以函数的形式调用时,this 永远都是 window(即:如 window.fun() 此时的对象就是 window)* 2.以方法的形式调用时,this 就是调用方法的那个对象*/function fun(){//console.log("a = "+a+", b = "+b);console.log(this.name);}// fun();//创建一个对象var obj = {name:"孙悟空",sayName:fun};var obj2 = {name:"沙和尚",sayName:fun};// console.log(obj.sayName == fun);// true// var name = "全局的name属性";// obj.sayName();// 输出结果为:孙悟空(原因:调用 sayName() 的对象是 obj,因此 this 指向的是 obj)//以函数形式调用,this 是 windowfun();//因此此时的输出结果是:全局的name属性//以方法的形式调用,this 是调用方法的对象//obj.sayName();obj2.sayName();// 沙和尚</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

其三、代码为:(输出调用方法对象的名字)
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">//创建一个 name 变量var name = "全局";//创建一个 fun() 函数function fun(){console.log(this.name);}//创建两个对象var obj = {name:"孙悟空",sayName:fun};var obj2 = {name:"沙和尚",sayName:fun};//我们希望调用 obj.sayName() 时可以输出 obj 的名字//obj.sayName();obj.sayName();// 输出结果为:孙悟空</script></head><body></body>
</html>
其四、结果为:
// 一进入页面后的控制台:

其五、代码为:判断this指向
<!-- 两种不同调用函数方法的 this 指向不同 -->
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script type="text/javascript">/*alert("hello");function fun(){a = 10;}*/var obj = {sayHello:function(){console.log(this); function test(){console.log(this);}test();}};obj.sayHello();// {sayHello: ƒ}(第一个 this 指向为 obj 对象),Window(第二个 this 指向为 Window 对象)var fun = obj.sayHello;fun();// Window(第一个 this 指向为 Window 对象),Window(第二个 this 指向为 Window 对象)</script></head><body></body>
</html>
其六、结果为:
// 一进入页面后的控制台:

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.

Ⅴ、新创建对象的方法:工厂方法创建对象
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 创建一个对象*/var obj = {name:"孙悟空",age:18,gender:"男",sayName:function(){alert(this.name);}};/** 使用工厂方法创建对象* 通过该方法可以大批量的创建对象*/function createPerson(name , age ,gender){//创建一个新的对象 var obj = new Object();//向对象中添加属性obj.name = name;obj.age = age;obj.gender = gender;obj.sayName = function(){alert(this.name);};//将新的对象返回return obj;}/** 用来创建狗的对象*/function createDog(name , age){var obj = new Object();obj.name = name;obj.age = age;obj.sayHello = function(){alert("汪汪~~");};return obj;}var obj2 = createPerson("猪八戒",28,"男");var obj3 = createPerson("白骨精",16,"女");var obj4 = createPerson("蜘蛛精",18,"女");/** 使用工厂方法创建的对象,使用的构造函数都是 Object* 所以创建的对象都是 Object 这个类型,* 就导致我们无法区分出多种不同类型的对象*///创建一个狗的对象var dog = createDog("旺财",3);console.log(dog);// {name: '旺财', age: 3, sayHello: ƒ}console.log(obj4);// {name: '蜘蛛精', age: 18, gender: '女', sayName: ƒ}</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

Ⅵ、构造函数:
其一、代码为:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript">/** 创建一个构造函数,专门用来创建 Person 对象的* 构造函数就是一个普通的函数,创建方式和普通函数没有区别,* 不同的是构造函数习惯上首字母大写* * * 构造函数和普通函数的区别就是调用方式的不同* 普通函数是直接调用,而构造函数需要使用 new 关键字来调用* * * 构造函数的执行流程:* 1.立刻创建一个新的对象* 2.将新建的对象设置为函数中 this,在构造函数中可以使用 this 来引用新建的对象* 3.逐行执行函数中的代码* 4.将新建的对象作为返回值返回* * * 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。* 我们将通过一个构造函数创建的对象,称为是该类的实例* * * this 的情况:* 1.当以函数的形式调用时,this 是 window* 2.当以方法的形式调用时,谁调用方法 this 就是谁* 3.当以构造函数的形式调用时,this 就是新创建的那个对象* */function Person(name , age , gender){this.name = name;this.age = age;this.gender = gender;this.sayName = function(){alert(this.name);};}function Dog(){}var per = new Person("孙悟空",18,"男");var per2 = new Person("玉兔精",16,"女");var per3 = new Person("奔波霸",38,"男");var dog = new Dog();console.log(per);// Person {name: '孙悟空', age: 18, gender: '男', sayName: ƒ}console.log(dog);// Dog {}/** 使用 instanceof 可以检查一个对象是否是一个类的实例* 语法:* 对象 instanceof 构造函数* 如果是,则返回 true,否则返回 false*/// console.log(per instanceof Person);// true// console.log(dog instanceof Person);// false/** 所有的对象都是 Object 的后代,* 所以任何对象和 Object 做 instanceof 检查时都会返回 true*/// console.log(dog instanceof Object);// true</script></head><body></body>
</html>
其二、结果为:
// 一进入页面后的控制台:

Ⅶ、小结:
其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、若有转发或引用本文章内容,请注明本博客地址(直接点击下面 url 跳转) https://blog.csdn.net/weixin_43405300,创作不易,且行且珍惜!
其三、有兴趣的话,可以多多关注这个专栏(Vue(Vue2+Vue3)面试必备专栏)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_11525646.html?spm=1001.2014.3001.5482
其四、再有兴趣的话,也可以多多关注这个专栏(Java)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_12654744.html?spm=1001.2014.3001.5482
