javaScirpt学习第五章(函数)-第二部分
javaScirpt学习第五章(函数)-第二部分
本次函数内容比较多,我们分了两不分。
- window 对象
- this 指向等问题
1、windows对象
Window对象
- 在浏览器中,浏览器为我们提供了一个window对象,可以直接访问
window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作
除此之外window对象还负责存储JS中的内置对象和浏览器的宿主对象- window对象的属性可以通过window对象访问,也可以直接访问
函数就可以认为是window对象的方法
- window对象的属性可以通过window对象访问,也可以直接访问
var 用来声明变量,作用和let相同,但是var不具有块作用域
- 在全局中使用var声明的变量,都会作为window对象的属性保存
- 使用function声明的函数,都会作为window的方法保存
- 使用let声明的变量不会存储在window对象中,而存在一个秘密的小地方(无法访问)
- var虽然没有块作用域,但有函数作用域
- 使用function声明的函数,都会作为window的方法保存
示例使用
当我们调用alert,console,confirm,xxx 时候,我们有没有想过,这些函数我们自己也没有定义,他们是怎么来的呢,其实在浏览器内部,有一个window对象负责管理这些所有的函数,包含默认的已经自定义的函数,都由这个统一管理
alert
alert(window);// object window
window.xx 使用
当我们声明了一个 var a = 10,实际上就是 window.a = 10 这种赋值操作;
- 向window对象中添加的属性会自动成为全局变量
window.a = 10;
console.log(a);// 10
声明函数使用window对象
function fn() {
alert(‘我是函数fn’);
}window.fn();
注意点
function fn2 () {
// var d = 22;//var虽然没有块作用域,但有函数作用域
d = 88;// 在局部作用域中,如果没有使用var或let声明变量,则变量会自动成为window对象的属性 也就是全局变量
}
fn2();//
console.log(d)//88
2、let和var以及函数执行顺序
变量的提升
-
使用var声明的变量,它会在所有代码执行前被声明
- 所以我们可以在变量声明前就访问变量
函数的提升
-
使用函数声明创建的函数,会在其他代码执行前被创建
- 所以我们可以在函数声明前调用函数
let声明的变量实际也会提升,但是在赋值之前解释器禁止对该变量的访问
变量提升
console.log(b);
var b = 10;// 在下面申明 undefined
//let b = 10;// 在下面申明 Cannot access ‘b’ before initialization
函数提升
fn();//我是fn函数方法-----》》》
//函数提升
function fn() {
console.log(‘我是fn函数方法-----》》》’)
}
对变量未声明
//var a = 10;
a = 10;// window.a = 10
3、小练习
<script>var a = 1;function fn() {a = 2;console.log(a);//2}fn();console.log(a);//2// 变量和函数的提升同样适用于函数作用域var a1 = 1;function fn1() {console.log("fn1-->",a1);//undefinedvar a1 = 2;console.log("fn1-->",a1);//2}fn1();console.log("a1-->",a1);//1// 定义形参就相当于在函数中声明了对应的变量,但是没有赋值var a2 = 22;function fn2(a2) {console.log("fn2-->",a2);//undefineda2 = 33;console.log("fn2-->",a2);//33}fn2();console.log("a2-->",a2);//22// 案例3var a3 = 33;function fn3(a3) {console.log('fn3-->',a3);//33a3 = 19;console.log('fn3-->',a3);// 19}fn3(a3);console.log('a3-->',a3);//19// 案例4 var a4 = 4;console.log('a4--->',a4);//4 // 函数名字叫 a4 function a4() {alert('fn--->a4')}console.log('a4--->',a4);//4 var a4 = 41;console.log('a4--->',a4);//41var a4 = function() {alert('fn--->a4->')}console.log('a4--->',a4);//函数内容var a4;console.log('a4--->',a4);//函数内容</script>
4、debug 使用
debug就是用来调试程序,停留在某一段地方,让代码一行一行的执行,让我们看到程序的变化使用。
第一种使用方式
打开浏览器的F12 快捷键
第二种方式
debugger // 在代码中打了一个断点这个时候代码就停留在这里了;
5、立即执行函数
立即执行函数(IIFE)
-
立即是一个匿名的函数,并它只会调用一次
-
可以利用IIFE来创建一个一次性的函数作用域,避免变量冲突的问题
注意
-
在开发中应该尽量减少直接在全局作用域中编写代码!
-
所以我们的代码要尽量编写的局部作用域
-
如果使用let声明的变量,可以使用{}来创建块作用域
示例使用
<script>// 使用let 申明变量 不使用var {let a = 10;}{let a = 20;}//console.log(a);//a is not defined// 函数里面写var 这种有自己的作用域function fn1() {var b = 10;}fn1();//console.log('b==>',b);// b is not defined// 希望可以创建一个只执行一次的匿名函数(function() {let c = 10;console.log('c==>',c);//c==> 10}());// 注意,如果我们需要写两个函数,一定记得要在函数结束后面加上分号// ,或者加上其他逻辑,避免连接到一起而不能解析//方式2 括号写到外面 (function() {let c = 10;console.log('c==>',c);//c==> 10}) ()
</script>
6、this
- 函数在执行时,JS解析器每次都会传递进一个隐含的参数
这个参数就叫做 this- this会指向一个对象
- this所指向的对象会根据函数调用方式的不同而不同
1.以函数形式调用时,this指向的是window
2.以方法的形式调用时,this指向的是调用方法的对象
…
- 通过this可以在方法中引用调用方法的对象
示例使用
<script>function fn() {console.log(this === window);// trueconsole.log('fn对象是什么',this)// Window }fn();// window 对象window.fn();// 如上// 对象调用const obj1 = {name: '孙悟空'};obj1.test = fn;obj1.test();// {name: '孙悟空', test: ƒ}const obj2 = {name: '猪八戒',test: fn}obj2.test();//{name: '猪八戒', test: ƒ} this 取谁调用,调用的对象是谁const obj3 = {name: '唐僧',sayHello: function () {console.log(this.name)}}const obj4 = {name: '唐僧1',sayHello: function () {console.log(this.name)}}obj3.sayHello();//唐僧obj4.sayHello();//唐僧唐僧1</script>
7、箭头函数
箭头函数:
([参数]) => 返回值
例子:
无参箭头函数:() => 返回值
一个参数的:a => 返回值
多个参数的:(a, b) => 返回值
只有一个语句的函数:() => 返回值
只返回一个对象的函数:() => ({…})
有多行语句的函数:() => {
…
return 返回值
}
-
箭头函数没有自己的this,它的this有外层作用域决定
-
箭头函数的this和它的调用方式无关
示例使用
<script>// 普通函数this function fn1() {console.log('fn1---->',this)}const fn2 = () => {console.log('fn2--->',this)}fn1();//Windowfn2();//Windowconst obj = {name: '孙悟空',fn1,//fn1:fn1fn2,sayHello() {console.log(this.name)function t() {console.log('t--->',this)}t();//Windowconst t2 = () => {console.log('t2--->',this);}t2();// 指向的是对象}}obj.fn1();// obj对象obj.fn2();// window 对象obj.sayHello();// 总结,箭头函数的this是,谁调用我,那么我得this就是谁// 其他函数的this 不定,箭头函数的指向比较稳定</script>
8、严格模式
JS运行代码的模式有两种:
-
正常模式
- 默认情况下代码都运行在正常模式中,
在正常模式,语法检查并不严格
它的原则是:能不报错的地方尽量不报错 - 这种处理方式导致代码的运行性能较差
- 默认情况下代码都运行在正常模式中,
-
严格模式
- 在严格模式下,语法检查变得严格
1.禁止一些语法
2.更容易报错
3.提升了性能
- 在严格模式下,语法检查变得严格
-
在开发中,应该尽量使用严格模式,
这样可以将一些隐藏的问题消灭在萌芽阶段,
同时也能提升代码的运行性能
实例使用
<script>"use strict"//全局的严格模式let a = 10console.log(a)// b = 11;//b is not defined// console.log(b)// 函数里面使用严格模式function fn() {'use strict'//c = '123'//: c is not defined}fn()</script>