重学JavaScript

P1

五大主流浏览器

  1. IE浏览器(Internet explorer):Trident内核,也是俗称的IE内核;
  2. 谷歌浏览器(Chrome):Chrome内核,以前是Webkit内核,现在是Blink内核;
  3. 火狐浏览器(Firefox):Gecko内核,俗称Firefox内核;
  4. 苹果浏览器(Safari):Webkit内核;
  5. 欧朋浏览器(Opera):最初是自己的Presto内核,后来加入谷歌大军,从Webkit又到了Blink内核;

浏览器的历史

来自哔哩哔哩:
浏览器全球发展史(上)
浏览器全球发展史(下)

ECMA

欧洲计算机制造商协会(European Computer Manufacturers Association)。它是评估、开发、认可电信、计算机的标准的一个协会。它有一个标准清单,里面有很多的标准。其中ECMA-262 是脚本语言的规范:ECMAScript
所以我们所说的ES5、ES6是一个标准。

编程语言

分为两个比较大的类:

  • 编译型:
    • 翻译过程:源码 -> 编译器 -> 机器语言 -> 可执行的文件
    • 优点:不需要根据不同的系统平台进行移植(有相应的解释器就能执行)
  • 解释型:
    • 翻译过程:源码 -> 解释器 -> 解释一行就执行一行

JavaScript

组成:

  • ECMAscript:
    • 语法、变量、关键字、保留字、值、原始类型、引用类型运算、对象、继承、函数……
  • 文档对象模型:DOM:Document Object Model
    • W3C规范 获取修改添加删除HTML元素
  • 浏览器对象模型:BOM:Browser Object Model
    • 没有规范 滚动条 窗口宽高 冒泡捕获 键盘事件……

JS引擎是单线程的,但是可以模拟多线程
轮转时间片:短时间之内轮流执行两个或者多个任务的片段
步骤:
1.任务1 任务2
2.切分 任务1 任务2
3.随机排列这些任务片段
4.按照这个队列顺序将任务片段送进JS线程
4.JS线程执行一个又一个的任务片段

变量

变量就相当于是个容器,用来存储数据,作用是后续使用,可以把变量存进去拿出来。
变量在使用时分两步:声明变量变量赋值

var a //声明变量
a = 3; // 变量赋值
var a = 3;// 声明变量并赋值
= 赋值的意思 ,把后面的值赋给前面的变量

命名规范:

  1. 由数字、字母、下划线和美元符号($)组成,如age、name
  2. 严格区分大小写,如app和App是两个变量
  3. 不能以数字开头,如18age是错误的变量名
  4. 不能是关键字、保留字,如 var 、 for、 while 等是错误的变量名
  5. 要尽量做到‘见其名知其意’,如age表示年龄,num表示数字
  6. 建议遵循驼峰命名法,首字母小写,后面的单词首字母大写,如myFirstName

数据类型

数据类型

  • 值类型(基本类型):
    • 字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
  • 引用数据类型(对象类型):
    • 对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。

注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
在这里插入图片描述

P2运算符

算术运算符

加法:+:任何数据类型的值 + 字符串都是字符串

a = “str” + “str” //strstr
b = “str” + undefined // strundefined
c =“str” + 1 + 1 //str11
d = “str” + (1 + 1) //str2
e = 1+1+“str” + (1 +1) //2str2

除法:/:

a = 0/0 ; // NaN -> Not a Number 非数
b = 1/NaN ; // NaN
c = 1/0 ; // Infinity ->正无穷 数字类型
d = -1/0 ; // -Infinity ->负无穷 数字类型

取余:%:

console.log(5%2) ; // 1
console.log(5%3) ; // 2
console.log(0%6) ; // 0

交换值的问题:

var a = 1,b =2;
a、b值交换:

  1. var c = a ; a = b ; b = c ;
  2. a = a + b ; // a = 3
  3. b = a - b ; // 3 - 2 = 1
  4. a = a - b ; // 3 - 1 = 2

递增递减运算符++, - -

var a = 1 ; a = a + 1 ; => a + +

先打印后运算

var a = 1 ;
console.log(a++) // 1
console.log(++a) // 2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

比较运算符

比较:> , < , >= , <= , = = , = = = , ! = , ! =
数字对比 : 就按照数字的来
字符串 - 数字对比 : 先把字符串转换为数字
字符串对比 : 相对应的ASCII码
在这里插入图片描述
在这里插入图片描述
相等是不看数字类型的
全等是需要看数据类型是否相等的
NaN与包括自己在内任何东西都不相等

逻辑运算符

假: undefined 、null 、NaN 、“” 、0 、false
在这里插入图片描述

var a = 1 && 2 && undefined && 10 ;
//遇到真就往后走,
//遇到假或走到最后就返回当前的值
var b = 0 || null || 1 || 0;
//遇到假就往后走,
//遇到真或走到最后就返回当前的值
console.log(a,b); //undefined 1

P3循环

for循环

写法:

for(){
执行语句
}
步骤:
1.声明变量i= 0
2.if ( i < 10 ){
console.log( i )
}
3.i++
4.继续第2步
if ( i < 10 ){ 如果这一步不满足条件,就停止循环
console.log( i )
}
5.继续第3步 i++
==========================================>
可以先把声明变量提出来
var i = 0 ;
for ( ; i < 10 ; ) {
console.log ( i ) ;
i++ ;
}

打印出1 - 10

        var i = 1;
        for (; i;) {
            console.log(i);
            i++;
            if (i == 11) {
                i = 0; // break;
            }
        }

从 0 开始做加法,加到什么时候 ,总和是小于100的。

        var sum = 0;
        for(var i = 0; i<100;i++){
            sum += i
            if(sum >= 100){
                break;
            }
            console.log(i,sum);
        }

100以内的数,跳过可以被7整除或个位数是7的数。

        for (var i = 0; i <= 100; i++) {
            if(i % 7 == 0 || i % 10 == 7){
                continue;
            }else{
                console.log(i);
            }
        }

打印100里,可以被4, 5, 6, 整除的数

        for (var i = 0; i <= 100; i++) {
            if (i % 4 == 0 || i % 5 == 0 || i % 6 == 0) {
                console.log(i);
            }
        }

打印0-100的数,()只能有一句,不能写比较,{}不能出现i + + , i - -
for ( 表达式1 ;表达式2;表达式3 ){ }
当表达式2为假(undefined 、null 、NaN 、“” 、0 、false)时,循环结束。中间这个只返回true和false

        var i = 101;
        for (; i--;) {
            console.log(i);
        }

10的n次方

        var n = 5;
        var num = 1
        for(var i = 0;i<n;i++){
            num *= 10;
        }
        console.log(num); //100000

n 的阶乘

        var n = 5;
        var num = 1;
        for (var i = 1; i <= 5; i++) {
            num *= i;
        }
        console.log(num); //120

789打印出987

        var num = 789;
        var a = num % 10;
        var b = (num - a) % 100 / 10
        var c = (num - a - b * 10) / 100;
        console.log("" + a + b + c);

打印三个数中的最大的数

        var a = 6,
            b = 2,
            c = 3;
        if (a > b) {
            if (a > c) {
                console.log(a);
            } else {
                console.log(c);
            }
        } else {
            if (b > c) {
                console.log(b);
            } else {
                console.log(c);
            }
        }

打印100以内的质数(仅仅能被1和自己整除的数)

        var c = 0;
        for (var i = 2; i < 100; i++) {
            for (var j = 1; j <= i; j++) {
                if (i % j == 0) {
                    c++
                }
            }
            if (c == 2) {
                console.log(i);
            }
            c = 0;
        }

引用值

array、object、function、date、RegExp。

array:

取值:数组取值从0开始
赋值:arr[3] = null
长度:arr.length
取每一位:循环

var arr = [ 1 , 2 , 3 , 4 , 5 , ]

object:

在这里插入图片描述

typeof

用来判断类型:number、string、boolean、object ( = 引用类型 object和array =>Object )、function、undefined

 		console.log(typeof(123)); //number
        console.log(typeof('123')); //string
        console.log(typeof(true)); //boolean
        console.log(typeof({})); //object
        console.log(typeof([])); //object
        //object = 引用类型 object 和 array =>Object
        console.log(typeof(null)); //object 是个历史遗留下来的bug
        console.log(typeof(undefined)); //undefined
        console.log(typeof(function () {}));//function
        //-----------------------------------
        console.log(typeof(1-1)); //number
        console.log(typeof(1-"1")); //number
        console.log(typeof("1"-"1")); //number
        //-----------------------------------
        console.log(a); //a未被定义 引用报错
        console.log(typeof(a)); //undefined
        //-----------------------------------
        // 判断出来的这个类型的名字再判断,名字肯定是string
        console.log(typeof(typeof(12))); //string
        console.log(typeof(typeof(a))); //string
显示类型转换

number转换成数字

        console.log(typeof (Number('123')) + '-' + Number('123'));  //number-123
        console.log(typeof (Number('true')) + '-' + Number('true'));  //number-NaN
        console.log(typeof (Number(true)) + '-' + Number(true));  //number-1
        console.log(typeof (Number(false)) + '-' + Number(false));  //number-0
        console.log(typeof (Number(null)) + '-' + Number(null));  //number-0
        console.log(typeof (Number(undefined)) + '-' + Number(undefined));  //number-NaN
        console.log(typeof (Number('a')) + '-' + Number('a'));  //number-NaN
        console.log(typeof (Number('1a')) + '-' + Number('1a'));  //number-NaN
        console.log(typeof (Number('3.14')) + '-' + Number('3.14'));  //number-3.14

parseInt转换成整型

        console.log(typeof (parseInt('123')) + '-' + parseInt('123'));  //number-123
        console.log(typeof (parseInt(true)) + '-' + parseInt(true));  //number-NaN
        console.log(typeof (parseInt(null)) + '-' + parseInt(null));  //number-NaN
        console.log(typeof (parseInt(undefined)) + '-' + parseInt(undefined));  //number-NaN
        console.log(typeof (parseInt(NaN)) + '-' + parseInt(NaN));  //number-NaN
        console.log(typeof (parseInt('3.99')) + '-' + parseInt('3.99'));  //number-3
        //-----------------------------------进制radix
        console.log(typeof (parseInt('10',16)) + '-' + parseInt('10',16));  //number-16(十进制的10的十六进制)
        console.log(typeof (parseInt('b',16)) + '-' + parseInt('b',16));  //number-11
        //-----------------------------------
        console.log(typeof (parseInt('abc123') )+ '-' + parseInt('abc123'));  //number-NaN
        console.log(typeof (parseInt('123abc') )+ '-' + parseInt('123abc'));  //number-123
        console.log(typeof (parseInt('1abc23') )+ '-' + parseInt('1abc23'));  //number-1

parseFloat:函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。

        console.log(parseFloat('3.14')); //3.14
        console.log(parseFloat('3.1415926')); //3.1415926
        console.log(parseFloat('3')); //3
        //-----------------------------------
        //3.1415926要小数后两位
        var num = parseFloat('3.1465926');
        console.log(num.toFixed(2)); // 3.15 、四舍五入的

String

 console.log(typeof(String(123))); //string
        console.log(typeof(123+'')); //string
        console.log('3.14'.toString()); //3.14字符串
        console.log(null.toString()); //报错
        //-----------------------------------进制radix
        console.log( parseInt(100,2).toString(16)); //4

Boolean
undefined 、null 、NaN 、“” 、0 、false,其他都是true

        console.log(Boolean(1));  //true
        console.log(Boolean(null)); //false
隐式类型转换
        var a = '123'; //Number(a)
        a++;
        console.log(a);
        //-----------------------------------
        var a = 'a' + 1;
        console.log(a); //a1
        //-----------------------------------
        var a = '3' * 2; // * / - % =>string->number
        console.log(a); //6
        //-----------------------------------
        var a = '1' > 2;
        console.log(a); //false
        //-----------------------------------
        var a = 1 > '2'; // > < >= <=都要转换成number再进行对比,除了下面的一种
        console.log(a); //false
        //-----------------------------------
        var a = 'a' > 'b';
        console.log(a);//false
        //-----------------------------------
        var a = 1 == '1'
        console.log(a); //true
        //-----------------------------------
        var a = 1 === '1' //不进行隐式转换
        console.log(a); //false
        //-----------------------------------
        var a = 1 != '2'
        console.log(a); //true
        //-----------------------------------
        var a = NaN == NaN;
        console.log(a); //false
        //-----------------------------------
        var a1 = 2 > 1 > 3;
        var a2 = 2 > 1 == 1;
        console.log(a1); //false
        console.log(a2); //true
        //-----------------------------------
        var a1 = undefined > 0;
        var a2 = undefined < 0;
        var a3 = undefined = 0;
        var a4 = undefined == 0;
        
        var b1 = null > 0;
        var b2 = null < 0;
        var b4 = null == 0;

        var c1 = undefined == null;
        var c2 = undefined === null;

        console.log(a1); //false
        console.log(a2); //false
        console.log(a3); //0
        console.log(a4); //false

        console.log(b1); //false
        console.log(b2); //false
        console.log(b4); //false

        console.log(c1); //true
        console.log(c2); //false
        //-----------------------------------
        var num = '123';
        console.log(typeof(+ num) + ':' + +num); //number:123
        console.log(typeof(- num) + ':' + -num); //number:-123

        var num2 = 'abc';
        console.log(typeof(+ num2) + ':' + +num2); //number:NaN
        console.log(typeof(- num2) + ':' + -num2); //number:NaN

isNaN ->Number(值)->NaN->bool

console.log(isNaN(NaN)); //true
        console.log(isNaN(123)); //false
        console.log(isNaN("123")); //false
        console.log(isNaN("a")); //true
        console.log(isNaN(null)); //false
        console.log(isNaN(undefined)); //true

do while 循环

无论怎么样,都是要循环一次的。
在这里插入图片描述

斐波拉契数列

        /**
         * n1  n2  n3
         * 1   1   2   3   5   8
         *     n1  n2  n3
         *         n1  n2  n3
         *             n1  n2  n3
        */
        
var n = parseInt(window.prompt('请输入第几位'))
        if (n <= 0) {
            console.log('输入错误');
        } else {
            var n1 = 1, n2 = 1, n3;
            if (n <= 2) {
                console.log(1);
            } else {
                for (var i = 2; i < n; i++) {
                    n3 = n1 + n2;
                    n1 = n2;
                    n2 = n3;
                }
                console.log(n3);
            }

        }

P4函数

一个固定的功能或者是程序段被封装的过程
实现一个固定的功能或者是程序
在这个封装体中需要一个入口和一个出口
入口就是参数,出口就是返回
高内聚低耦合 – > 模块的单一责任制

函数

函数声明(最基本的函数写法)

        function test() {
            var a = 1,
                b = 2;
            console.log(a,b);
        }
        test();

匿名函数表达式 函数字面量

        var test = function(){ 
            var a = 1,
                b = 2;
            console.log(a,b);
        }
        test();

函数的组成部分:
function 函数名 参数(可选) 返回值() return 。

        var aa = parseInt(window.prompt('a'));
        var bb = parseInt(window.prompt('b'));
        function test(a,b) { //(a,b)占位 -> 形式上占位,形式参数,形参。和实参是一一对应的。
            console.log(a+b);
        }
        test(aa,bb) //实际参数,实参。

形参与实参

function 函数名(形参1、形参2……){
//函数体代码
}
函数名(实参1、实参2……)

  • 形参和实参数量可不等
  • 在实参里面传了值的,可以在函数内部修改实参的值。如果实参里面没有这个值,给形参赋值,是没有用的。

在这里插入图片描述
实参求和

        function sum() {
            var a = 0;
            for(var i = 0 ;i <arguments.length;i++){
                a += arguments[i];
            }
            console.log(a);
        }
        sum(1,2,3,4)

在函数内部可修改实参的值

        function test(a,b) {
            a = 3;
            console.log(arguments[0]);//3
        }
        test(1,2)

实参并没有传递,就相当于是个undefined。

        function test(a,b) {
            b = 3;
            console.log(arguments[1]); //undefined
        }
        test(1);

return

第一个作用:终止函数执行
return在哪个位置,哪个位置就结束。默认是在最后return。
在这里插入图片描述
第二个作用:返回值
在这里插入图片描述
在这里插入图片描述

变量

函数外部:全局变量
函数内部:局部变量
函数体内部可以访问外部的变量,外部的变量不能访问内部的变量。
涉及到 [ [ scope ] ] 的问题

        a = 2;
        function test() {
            var b = 1;
            console.log(a); //2
        }
        test()
        console.log(b);//b is not defined
        // ----------------------------------------
        // a是全局变量 函数内部的是局部变量 [scope]
        //内部能访问修改外部,外部不能访问修改内部。
        a =1;
        function test1() {
            var b = 2;
            console.log(a); //1
            function test2() {
                var c = 3;
                console.log(b); //2
                console.log(a); //1
            }
            test2();
            console.log(c);//c is not defined
        }
        test1()

function 都有自己的独立作用域

      function test1() {
            var a = 1;
            console.log(b); // not defined
        }
        function test2() {
            var b = 2;
            console.log(a); // not defined
        }

        test1()
        test2()

P5

形参b没有赋值,就是undefined。

        function test(a = 1, b) {
            console.log(a); //1
            console.log(b); //undefined
        }
        test()

给b传入实参, a要选用默认值的话, 就给a传实参传undefined

----------------es5-----------------------------
        function test(a,b) {
            var a = arguments[0] || 1;
            var b = arguments[1] || 2;
            console.log(a+b);
        }
        test()

        function test(a, b) {
            var a, b;
            if (typeof (arguments[0]) !== 'undefined'){
                a = arguments[0];
            } else {
                a = 1;
            }
            if (typeof (arguments[1]) !== 'undefined') {
                b = arguments[1];
            } else {
                b = 2;
            }
            console.log(a + b);
        }
        test()

        function test(a, b) {
            var a = typeof(arguments[0])!== 'undefined' ? arguments[0] :1;
            var b = typeof(arguments[1])!== 'undefined' ? arguments[1] :2;
            console.log(a + b);
        }
        test()
----------------es6-----------------------------
        function test(a = 1, b) {
            console.log(a); //1
            console.log(b); //2
        }
        test(undefined, 2)

        function test(a = undefined, b) {
            console.log(a); //1
            console.log(b); //2
        }
        test(1, 2)

递归作业

作业1:定义一个函数,算出n的阶乘,不能用for循环

        //n的阶乘 ->不能for循环 -> 递归
        //fact(n)
        //n! = n*(n-1)! 规律
        //出口

        function fact(n) {
            if(n === 1){
                return 1;
            }
            return n * fact(n-1);
        }
        console.log(fact(5)); //120

步骤解析
在这里插入图片描述
作业2:定义一个函数,算出斐波那契数列的第N位,不能用for循环

        // 循环:n3 = n2 + n1;
        // 出口:n <= 0 ; n <= 2;
        function fb(n) {
            if(n <= 2){
                return 1;
            }
            return fb(n-1) + fb(n-2)
        }
        console.log(fb(5)); //5

步骤解析
在这里插入图片描述

预编译流程

1.检查通篇的语法错误
1.5.预编译的过程
2.解释一行,执行一行

函数声明整体提示,变量只有声明提升,赋值是不提升的

        test();
        function test() {
            console.log(1); //1
        }
        //----------------------------------
        console.log(a); //undefined
        var a = 10;

        console.log(a); //undefined
        var a ;

        console.log(a); //a is not defined

暗示全局变量 imply global variable:

实际上在全局,写不写var都属于一个东西 window ,window是个系统内置的对象
所以在全局的概念里 a = window.a ; b = window.b。

        var a = 1;
        console.log(a); // 1
        console.log(window.a); //1

        b = 1;
        console.log(b);  //1

        // 实际上在全局,写不写var都属于一个东西 window ,window是个系统内置的对象
        // 所以在全局的概念里 a = window.a ; b = window.b

        // window = {
        //     a = 1,
        //     b = 2
        // }

在函数内部,没有声明这个变量,而直接给这个变量赋值的话,那它就提升到全局变量,到window里去了

 function test() {
            var a = b = 1; //步骤:先声明一个a,把1给b,把b的值给a ,b并没有在function内部去声明
        }
        test();
        console.log(b); //1
        console.log(window.b); //1
        console.log(a); //a is not defined
        console.log(window.a); // undefined

AO

预编译的过程:AO : activation object 活跃对象 函数上下文

  1. 寻找函数的形参和变量声明
  2. 把实参的参数值赋给形参
  3. 寻找函数声明,赋值函数体
  4. 执行函数
        function test(a) {
            console.log(a); //f a(){}
            var a = 1;
            console.log(a); //1
            function a(){}
            console.log(a); //1
            var b = function(){}
            console.log(b); //f(){}
            function d(){}
        }
        test(2)
        /**
         * 创建AO对象
         * AO = {
         *     1. 寻找函数的形参和变量声明
         *      a:undefined
         *      b:undefined
         *     2.把实参的参数值赋值给形参
         *      a:undefined -> a = 2
         *     3.寻找函数声明,赋值函数体
         *      a:undefined -> a = 2 -> function a(){}
         *      function d(){}
         *     4.执行函数
         *      a:undefined -> 
         *        a = 2 -> 
         *        function a(){} ->
         *        a = 1 
         *      b:undefined ->
         *        function(){}
         *      d:function d(){}
         * }
        */
    //-------------------------------------------
        function test(a,b) {
            console.log(a); //1
            c = 0;
            var c;
            a = 5;
            b = 6;
            console.log(b); //6
            function b(){}
            function d(){}
            console.log(b); //6
        }
        test(1)
        /**
         *  AO = {
         *      a:undefined->
         *        a = 1->
         *        a = 5
         *      b:undefined->
         *        function b(){}->
         *        b = 6
         *      c:undefined->
         *        c = 0
         *      d:function d(){}
         * }
        */

GO

GO:global object 全局上下文。 实际上GO === window

        var a = 1;
        function a() {
            console.log(a); //1
        }
        console.log(a); //1

        // GO global object 全局上下文
        /**
         * GO = {
         *  1.寻找变量声明
         *      a:undefined
         *  2.寻找函数声明
         *      a:undefined ->
         *        function a(){}
         *  3.执行
         *      a:undefined ->
         *        function a(){}-> 1
         * } 
        */
    //-------------------------------------------
        console.log(a,b); //ƒ a() {} undefined
        function a() {}
        var b = function(){}
        /**
         * GO = {
         *  1.寻找变量声明
         *      b:undefined
         *  2.寻找函数声明
         *      a:undefined ->
         *        function a(){}
         * } 
        */

AOGO

        function test() {
            var a = b = 1;
            console.log(b);
        }
        test();

        /**
         * GO = {
         *  b : 1,
         * }
         * 
         * AO = {
         *  a:undefined -> 1
         * }
         * 
        */
    //------------------------------------------- 
        var b = 3;
        console.log(a);
        function a(a) {
            console.log(a);
            var a = 2;
            console.log(a);
            function a() {}
            var b = 5;
            console.log(b);
        }
        a(1)
        
        /**
         * GO = {
         *  b:undefined, ->3
         *  a:function a(){...}
         * }
         * AO ={
         *  a:undefined 
         *      1
         *      function a() {}
         *      2
         *  b:undefined
         *      5
         * }
         * 
        */
    //-------------------------------------------
        a = 1;
        function test() {
            console.log(a); //undefined
            a = 2;
            console.log(a); //2
            var a = 3;
            console.log(a); //3 
        }
        test()
        var a;
        /**
         * GO = {
         *  a:undefined
         *      1
         *  test: function test(){...}
         * }
         * AO = {
         *  a : undefined
         *      2
         *      3
         * }
         * 
        */
    //-------------------------------------------
        function test() {
            console.log(b);//undefined
            if(a){ //不执行
                var b = 2;
            }
            c = 3;
            console.log(c); //3
        }

        var a; //undefined
        test();
        a = 1;
        console.log(a); //1

        /**
         * GO={
         *  a:undefined
         *  test : function test(){}
         *  c:3
         * }
         * AO={
         *  b:undefined
         * }
        */

笔试题:

        var a = false + 1 ;
        console.log(a); //1
    //-------------------------------------------
        var b = false == 1;
        console.log(b); //false
    //-------------------------------------------
        if(typeof(a) && (-true) + (+undefined) + ''){
            console.log('通过了'); //通过了
        }else{
            console.log('没通过');
        }

        console.log(a); // a is not defined
        console.log( typeof(a) ); //字符串的undefined 真
        console.log(-true); //-1
        console.log(+undefined); // NaN 也是数字类型
    //-------------------------------------------
        if(1 + 5 * '3' === 16) {
            console.log("通过了"); //通过了
        }else{
            console.log("未通过");
        }
    //-------------------------------------------
        console.log(!! ' ' + !!'' - !!false || '未通过'); //未通过

AOGO作业:

        function test() {
            return a;
            a = 1;
            function a() {}
            var a = 2;
        }
        console.log(test()); //f a(){}
    //-------------------------------------------
        console.log(test()); //2
        function test() {
            a = 1;
            function a() {}
            var a = 2;
            return a;
        }
    //-------------------------------------------
        a = 1;
        function test(e) {
            function e() {}
            arguments[0] = 2;
            console.log(e);//2
            if(a){
                var b = 3;
            }
            var c;
            a = 4;
            var a;
            console.log(b);//undefined
            f = 5;
            console.log(c); //undefined
            console.log(a); //4
        }
        var a;
        test(1);
        console.log(a); //1
        console.log(f); //5

P6 作用域、作用域链、预编译、闭包基础

AO - > 与function紧密相关 , 相当于是个独立的仓库
函数也是一种对象类型 引用类型 引用值
对象 -> 有些属性是我们无法访问的,js引擎内部固有的隐式属性
[[scope]]

  • 函数创建时,生产的一个JS内部的隐式属性。
  • 函数存储作用域链的容器,作用域链里面是AO/GO,作用域链就相当于是把这些AO/GO连起来。
    • AO/GO
      • AO:函数的执行期上下文
      • GO:全局的执行期上下文
      • 函数执行完成之后,AO是要销毁的
      • AO是一个即时的存储容器

分析图解:

在这里插入图片描述
每一个函数的作用域链上都有GO
在这里插入图片描述
一个函数都有自己的AO和全局的GO,并且AO排列在GO前
在这里插入图片描述
在执行之前(被定义的时候),这个环境和之前是一样的,只有执行了才会改变。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

        function a() {
            function b() {
                function c() {
                    
                }
                c();
            }
            b();
        }
        a();

        //a定义  a.[[scope]] -> 第0位 GO
        //a执行  a.[[scope]] -> 第0位 a - AO
        //                      第1位 GO
        //b定义  b.[[scope]] -> 第0位 a - AO
        //                      第1位 GO
        //b执行  b.[[scope]] -> 第0位 b -> AO
        //                      第1位 a ->AO
        //                      第2位 GO
        //c定义  c.[[scope]] -> 第0位 b -> AO
        //                      第1位 a ->AO
        //                      第2位 GO
        //c执行  c.[[scope]]  ->第0位 c-> AO
        //                      第1位 b -> AO
        //                      第2位 a ->AO
        //                      第3位 GO
        //c结束  c.[[scope]] -> 第1位 b -> AO
        //                      第2位 a ->AO
        //                      第3位 GO
        //b结束  b.[[scope]] -> 第0位 a - AO
        //                      第1位 GO
        //       c.[[scope]] x
        //a结束  a.[[scope]] -> 第0位 GO
        //       b.[[scope]] x

闭包

当内部函数被返回到外部并保存时,一定会产生闭包,
闭包会产生原来的作用域链不释放,
过渡的闭包可能会导致内存泄漏或加载过慢
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单闭包:

        function test() {
            var n = 100;
            function add() {
                n++;
                console.log(n); //101
            }
            function reduce() {
                n--;
                console.log(n); //100
            }

            return [add,reduce]
        }
        var arr = test();
        arr[0]();
        arr[1]();

面包管理器

        // 面包管理器
        function breadMgr(num) {
            var breadNum = arguments[0] || 10;
            function supply() {
                breadNum += 10;
                console.log(breadNum);
            }
            function sale() {
                breadNum --;
                console.log(breadNum);
            }
            return [supply,sale];
        }

        var breadMgr = breadMgr(50);

        breadMgr[0]();
        breadMgr[1]();
        breadMgr[1]();

在这里插入图片描述

星期天计划

        //星期天计划管理
        function sunSched() {
            var sunSched = '';
            var operation = {
                setSched:function(thing){
                    sunSched = thing;
                },
                showSched:function(){
                    console.log("My schedule on sunday is " + sunSched);
                }
            }
            return operation;
        }
        var sunSched = sunSched();

        sunSched.setSched('studying');
        sunSched.showSched();

在这里插入图片描述

P7立即执行函数、闭包深入、逗号运算符

前提

        function test1() {
            console.log(1);
        }
        function test2() {
            console.log(2);
        }
        test2(); //2

        function test3() {
            test1();
        }
        test3(); //1

做一个功能,页面加载完了,接收两个后台传过来的参数,每次加载页面的时候,都求这两个参数的和。

        // 做一个功能,页面加载完了,接收两个后台传过来的参数,每次加载页面的时候,都求这两个参数的和。

        add(1, 2);
        function add(a, b) {
            console.log(a + b);
        }

        console.log(add(1, 2));
        function add(a, b) {
            return a + b;
        }

自动执行,执行完成之后立即释放
立即执行函数 IIFE - Immediately Invoked Function Expression
1.自动执行2.执行完之后就立即销毁

(function(){
内容
})();
(function(){
内容
}()); //W3C建议

        (function () {
            var a = 1,
            b = 2;
           console.log(a+b); //3
        }());
        //----------------------------------
        (function (a,b) {
           console.log(a+b); //3
        }(1,2));
        //----------------------------------
        var num = (function (a,b) {
           return a+b;
        }(1,2));
        console.log(num); //3

()包裹任何东西都是表达式
一定是表达式才能被执行符号执行,
如果是(表达式的话),加不加名称都一样
在这里插入图片描述
在这里插入图片描述
逗号运算符,返回最后一个

        //逗号运算符,返回最后一个

        var num = (2-1,6+5,24+1)
        console.log(num); //25

经典案例:
在这里插入图片描述
如果要返回0-9 1-10

        // 第一种 
        function test() {
            for (var i = 0; i < 10; i++) {
                (function () {
                    document.write(i + ' '); //打印0-9
                    // document.write((i + 1) + ' ');//1-10
                }());
            }
        }
        test()

        // //第二种
        function test() {
            var arr = [];
            for (var i = 0; i < 10; i++) {
                arr[i] = function (num) {
                    document.write((num + 1) + ' ')
                }
            }
            return arr;
        }
        var myArr = test ();

        for (var j = 0; j < 10; j++) {
            myArr[j](j);
        }

        // //第三种
        function test() {
            var arr = [];
            for (var i = 0; i < 10; i++) {
                (function (j) {
                    arr[j] = function () {
                        document.write(j + ' ')
                    }
                })(i);
            }
            return arr;
        }
        var myArr = test();

        for (var j = 0; j < 10; j++) {
            myArr[j](j);
        }

题目:
在这里插入图片描述
面试题

        //(1,2); //返回的是2 fn()也是
        var fn = (
            function test1(){
                return 1;
            },

            function test2() {
                return '2';
            }
        )();
        console.log(typeof(fn)); //string
        //-------------------------------------
        var a = 10;
        if(function b(){}){
            a += typeof(b);
        }
        console.log(a);

P8闭包高级、对象、构造函数、实例化

闭包

        function test1() {
            function test2() {
                var b = 2;
                console.log(a); //1
            }
            var a = 1;
            return test2;
        }
        var c = 3;
        var test3 = test1();
        test3();

对象

        //对象
        var teacher = {
            name:'张三',
            age:32,
            sex:'male',
            height:176,
            weight:130,
            teach:function(){//对象里面叫方法,外面叫函数
                console.log('I am teacher');
            },
            smoke:function(){
                console.log(' I am smoking');
            },
            eat:function(){
                console.log('I am eating');
            }
        }

        //访问

        console.log(teacher.age); //32
        teacher.teach();//I am teacher
        console.log(teacher.teach);//f(){ console.log('I am teacher');}
        //-------------------------------------
        //增加

        teacher.address = '北京'
        teacher.drink = function(){
            console.log(' I am drinking');
        }
        teacher.drink() //I am drinking
        console.log(teacher); //增加了 address
        //-------------------------------------
        //修改

        teacher.height = 180;
        teacher.teach = function(){
            console.log('I am teacher HTML');
        }
        console.log(teacher);
        console.log(teacher.teach);
        //-------------------------------------
        //删除

        delete teacher.address;
        delete teacher.teach; //删除方法, 不用加()
        console.log(teacher);
        //-------------------------------------


        //每smoke体重件减1,每eat,体重+1
        var teacher = {
            name:'张三',
            age:32,
            sex:'male',
            height:176,
            weight:130,
            teach:function(){//对象里面叫方法,外面叫函数
                console.log('I am teacher');
            },
            smoke:function(){
                teacher.weight--
                console.log(teacher.weight);
            },
            eat:function(){
                teacher.weight++
                console.log(teacher.weight);
            }
        }
        teacher.smoke(); //129

this

this指的是对象本身
在这里插入图片描述

splice和indexOf

splice:
splice() 方法用于添加或删除数组中的元素。
注意:这种方法会改变原始数组。
在这里插入图片描述
indexOf:
在这里插入图片描述

        var num = 3;
        var arr = [1,2,3,4]

        for(var i = 0;i <arr.length;i++){
            if(arr[i] === num){
                arr.splice(i,1)
            }
        }
        console.log(arr); //[1,2,4]
        //---------------------------------
        var num = 5;
        var arr = [1,2,3,4]
        console.log(arr.indexOf(num)); //-1就代表不在这个数组里面

学生课堂上课案例
在这里插入图片描述
在这里插入图片描述

        var attendance = {
            students:[],
            total:6,
            join:function(name){
                this.students.push(name)
                console.log(this.students);
            },
            leave:function(name){
              var idx = this.students.indexOf(name);
              if(idx !== -1){
                this.students.splice(idx,1)
              }
              console.log(this.students);
            }
        }
        attendance.join('张三')
        attendance.join('李四')
        attendance.join('王五')
        attendance.leave('李四')

        var attendance = {
            students:[],
            total:6,
            join:function(name){
                this.students.push(name)
                if(this.students.length == this.total){
                    console.log(name + ' 到课,学生已到齐');
                }else{
                    console.log(name + ' 到课,学生未到齐');
                }
            },
            leave:function(name){
              var idx = this.students.indexOf(name);
              if(idx !== -1){
                this.students.splice(idx,1)
              }
              console.log(name + '早退');
              console.log(this.students);
            },
            classOver:function(){
                this.students = [];
                console.log('已下课');
            }
        }
        attendance.join('张三')
        attendance.join('李四')
        attendance.join('王五')
        attendance.join('赵六')
        attendance.join('吴七')
        attendance.join('孙八')
        attendance.leave('李四')
        attendance.classOver()

创建对象

对象字面量,对象直接量

        var obj ={
            name:'张三',
            sex:'male'
        }
        obj.name = '李四' 

构造函数
1.用系统内自带的构造函数—和对象字面量相等

        var obj = new Object();
        obj.name = '张三';
        obj.sex = '男士';
        console.log(obj);

2.自定义构造函数
大驼峰—表面上的区分

        // 自定义构造函数
        // 大驼峰---表面上的区分
        function Teacher() {
            this.name = '张三';
            this.sex = '男士';
            this.smoke = function(){
                console.log( 'I am smoking');
            }
        }
        var teacher = new Teacher(); //当new了之后才有this
        console.log(teacher);

之间互相不同,改变任意对象的属性和方法与另一个无关

        function Teacher() {
            this.name = '张三';
            this.sex = '男士';
            this.smoke = function(){
                console.log( 'I am smoking');
            }
        }
        var teacher1 = new Teacher(); //当new了之后才有this
        var teacher2 = new Teacher(); 
        teacher1.name = '李四'
        console.log(teacher1,teacher2);
        function Teacher(opt) {
            this.name = opt.name;
            this.age = opt.age;
        }

        var t1 = new Teacher({
            name:'张三',
            age:12
        })
        var t2 = new Teacher({
            name:'李四',
            age:13
        })
        
        console.log(t1);
        console.log(t2);

P9构造函数及实例化原理、包装类

作业

1.累加器 0;

        // 1.累加器 0  闭包
        function test() {
            var num = 0; 
            function add() {
                console.log(++num); //先自加再打印
            }
            return add;
        }
        var add = test();
        add();
        add();
        add();

2.一个班级,学生名字保存在一个数组里,两个方法写在函数中的一个对象里,第一个方法加入班级,第二个方法离开班级,每次加入或离开,都需要打印新的学生名单

        function myClass() {
            var students = []; //保存的是学生的名字
            var operations = { //定义一个对象方法
                join:function(name){ //加入
                    students.push(name);
                    console.log(students);
                },
                leave:function(name){ //离开
                    // for(var i = 0; i < students.length;i++){
                    //     var item = students[i] //优化for循环行能
                    //     if(item === name){
                    //         students.splice(i,1);
                    //     }
                    // }
                    var idx = students.indexOf(name);
                    if(idx !== -1){
                        students.splice(idx,1)
                    }

                    console.log(students);
                }
            }
            return operations;
        }
        var obj = myClass();
        obj.join('张三');
        obj.join('李四');
        obj.join('王五');
        obj.leave('李四')

复习上节课
在这里插入图片描述

实例化原理

不执行this不存在,一旦执行了,this就存在
this在没有实例化的时候,指向是windo,一旦实例化了,指向的是对象
在这里插入图片描述
原理

        function Car(color,brand){
            this.color = color;
            this.brand = brand;
        }
        //隐藏了一个 return this;
        //所以这个new仅仅是把这个this给造出来了,改变this指向
        var car1 = new Car('red','Benz');

        console.log(car1.color);

        /**
         * 1.页面一加载的时候肯定有GO
         * GO = {
         *      Car:(function),
         *      3.log执行的时候
         *      car1:{
         *          color:'red',
         *          brand:'Benz'
         *      }
         * }
         * 
         * 2.Car一执行,先保存一个this{}空对象,再往里加
         * AO = {
         *      this:{
         *          color:color,
         *          brand:brand
         *      }
         * }
         * 
         * */

new的时候就是系统把原本指向windows的指向了实例化对象
在这里插入图片描述
引用值 {} [] function
构造函数当中return的是引用值的时候,就有用,return的是原始值(number,string,undefined)之类的,就没有影响

        function Car() {
            this.color = 'red';
            this.brand = 'Benz';

            //return this
            // return 123  //red
            // return 'abc' //red
            // return {} //undefined
            //   return [] //undefined
        }

        var car = new Car;
        console.log(car.color);

包装类

var a = 1;的时候,原始值是没有自己的方法和属性,就没有a.length啊之类的。
但是当一个数字经过了new之后,就会变成一个对象,及可以设置相应的属性和方法
在这里插入图片描述
可以参与运算,对象又回到了原始值
在这里插入图片描述
像这种在js里有三种,把原始值转换成对象的方法
new Number
new String
new Boolean
null 和 undefined 是不可以设置任何的属性和方法的。

数组的截断方法
在这里插入图片描述
字符串 第一步就是new了一个string,设置length为1,但是abc不为1,就delete删除了
在这里插入图片描述

面试题

        var name = 'abc'
        name += 10; //'abc'
        var type = typeof(name); //'string'

        if(type.length === 6){ //true
            type.text = 'string'; //new String(type).text = 'string' 没地方保存 delete
        }

        console.log(type.text); //undefined

在这里插入图片描述
2.
在这里插入图片描述
3.
在这里插入图片描述
4.
在这里插入图片描述
5.
在这里插入图片描述
6.
在这里插入图片描述

P10原型、原型链、闭包和立即执行函数

作业:
写一个构造函数,接收数字类型的参数,参数数量不定,完成参数相加和相乘的功能

        function Compute() {
            var args = arguments,res;
            this.plus = function(){
                res = 0;
                loop('add',res);
            }
            this.times = function(){
                res = 1;
                loop('mul',res);
            }
            function loop(method,res) {
                for(var i = 0;i < args.length; i++){
                    var item = args[i];
                    if(method === 'add'){
                        res += item;
                    }else if(method === 'mul'){
                        res *= item;
                    }
                }
                console.log(res);
            }
        }
        var compute = new Compute(2,4,6);
        compute.plus(); //12
        compute.times(); //48

原型

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值