递归+作用域+立即执行函数+闭包+对象+包装类--大一下四、五周笔记

递归

两个要求

  1. 找规律
  2. 找出口

其实是比较耗时间的一种方法

js执行三部曲

语法分析

就是最开始通篇扫描检查有无基础错误

预编译

  1. 函数声明整体提升,就是说,如果里面存在函数,编译器会把函数直接提在程序的最前面

  2. 变量声明提升

  3. imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象(window)所有

  4. 一切声明的全局变量,全是window的属性(在全局范围内
    例如

a = 10;
window.a = 10;
window {
    a : 123
}
// 这三者的意义是一样的
  1. window就是全局的域

四部曲

预编译发生在函数执行的前一刻

  1. 创建AO对象(Activation Object)(执行期上下文)
  2. 找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined
  3. 将实参值和形参统一
  4. 在函数体里面找函数声明,值赋予函数体

在全局里面的第一步有些许不一样,第一步是生成一个GO对象Global Object

GO也就是window

if里面不能声明function

解释执行

就是执行函数

作用域

[[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,这就是其中一个
指的就是我们所说的作用域,其中存储了运行期上下文的集合

作用域链:scope中所存储的执行期上下文对象的集合,这个集合呈链式链接,叫做作用域链

运行期上下文:当函数执行的时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,所产生的执行上下文被销毁

查找变量:在哪个函数里面查找变量,就从那个函数的作用域链的顶端一次向下查找(感觉类似栈的结构)

    function a(){

        function b(){

            var b = 234;
        }

        var a = 123;
        b();

    }
    var glob = 100;
    
    a();

在这里插入图片描述

b访问的AO就是a产生的AO,指向的地方是一样的

函数执行完之后销毁执行期上下文,就是删除地址,不会删除内存

    function a (){
        function b() {
            var bbb = 234;
            document.write(aaa);
        }

        var aaa = 123;
        return b;
    }

    var glob = 100;
    var demo = a();
    demo();

将函数内部生成的函数保存在外部就会生成闭包

    function a(){

        function b(){
            num ++;
            console.log(num);
        }

        var num = 100;
        
        return b;
    }

    var demo = a();

    demo();
    demo();

上述输出结果为101,102,在这种情况下修改的直接是最开始AO里面的数据
return b;其实就是在b未执行的情况下,先将他定义,他的scope里面此时有a的AO和整体的GO

立即执行函数

定义:此类函数没有声明,只在一次执行过后即释放。适合做初始化工作。
针对初始化功能的函数(只被执行一次,或者希望他只被执行一次的函数)

// 第一种
    (function (){
        // 上面的括号用来放形参
    }());//末尾的括号用来放实参
    // W3C建议上面这种
    // 第二种
    (function (){})();
    var test = function () {
        console.log("a");
    }();
    // 第二种里面两种表达的意思相同

只有表达式才能被执行符号执行

被执行符号(就是小括号)执行的时候,函数名会被自动忽略,也就是说,这个函数变成了立即执行函数

闭包

当内部函数被保存到外部时,将会生成闭包,闭包会导致原有作用域链不释放,造成内存泄漏

闭包作用

  1. 实现公有变量
    eg:函数累加器
    function test() {

        var num = 100;
        function a() {
            num ++;
            console.log(num);
        }
        function b() {
            num --;
            console.log(num);
        }
        return [a,b];


    }
    var MyArry = test();
    MyArry[0]();
    MyArry[1](); 

输出结果为101,100,因为MyArry1是在101的基础上进行自减的

  1. 可以做缓存(存储结构)
    eg:eater
    function eater() {
            var food = "";
            var obj = {
                eat : function() {
                    console.log("I am eating " + food);
                    food = "";
                },
                push : function (myfood) {
                    food = myfood ;
                }
            }
            return obj;
        }

        var eater1 = eater();

        eater1.push("banana");
        eater1.eat();
    }

  1. 可以实现分装,变量私有化
    eg:Person();
function Person(name, wife) {
    var girlFriend = 'xiaoliu';
// 此时的girlFriend就是私有化属性,在console调控台上是查看不到的,但是属性是真实存在的,而且在下面三个函数执行的时候,形成闭包,三个函数都指向Person的OA,所以可以对该属性进行修改打印之类的行为
    this.name = name;
    this.wife = wife;

    this.changeWife = function(){
        this.wife = girlFriend;
    }
    this.changeGirlFriend = function(target){
        girlFriend = target;
    }
    this.sayGirlFriend = function(){
        console.log(girlFriend);
    }
}
var people = new Person("xiaoli","xiaofen");

  1. 模块化开发,防止污染全局变量
var name = 'bcd';
var init = (function () {
    var name = 'abc';

    function callName() {
        console.log(name);
    }

    return function (){
        callName();
    }

}())

init();
// 最后打印结果为abc
  • 一个关于闭包的小demo
    函数目的:按顺序输出0-9
    function test() {
        var arr = [];
        for(var i = 0; i < 10; i ++){
            arr[i] = function () {
                document.write(i + " ");
            }
        }
        return arr;
    }

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

输出结果如图
在这里插入图片描述

为什么会出现如下情况呢?
因为在最初执行的时候,在test函数执行的时候,数组的赋值相当于将函数体赋值在数组里面,就是相当于函数引用,赋值就相当于赋值了整个匿名函数体,里面的匿名函数并没有执行,直到在下面for循环里面进行打印的时候,函数function () {document.write(i + " ");}才执行,此时其实就已经形成了闭包了,test的AO里面的i在结束最初的for循环的时候就变成了10,在匿名函数执行的时候,检索到的i就已经是10了,所以循环打印输出10
就相当于10个函数在外部访问10个i,然后i都是10
解决:

    function test() {
        var arr = [];
        for(var i = 0; i < 10; i ++){
            (function (j) {
                arr[j] = function () {
                    document.write(j + " ");
                }
            }(i))
            
        }
        return arr;
    }

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

数组的每一个里面的保存的函数都会有一个立即执行函数的AO,每一个都立即执行函数都不一样,所以在那些的立即执行函数里面的j都是不一样的

对象

存在属性值和属性名,类似于c语言中的结构体,属性名方便于让我们找到属性值,每一个属性直接用逗号隔开

  1. 增加对象的属性
    直接在下面用 对象名.新的属性名 = 进行赋值就好。
    在这里插入图片描述

在对象里面修改属性值,需要给属性值加上对象名,或者用this来代替对象名

  1. 删除属性
    直接delete + 对象名.属性名,然后就会被删除,在对象中未定义的属性返回值都是undefined

  2. 修改属性
    直接在定义的下面选择好属性,然后直接修改属性值

  3. 查看属性
    直接在控制台查看,或者console.log查看,不能用document.write查看,用这个查看只能看到输出这个[object Object]

对象的创建方法

  1. var obj = {};
    plainObject 对象自变量/对象直接量

  2. 构造函数
    1)系统自带的构造函数 Object()
    new Object()会返回一个对象,需要一个变量来接受

var obj = new Object();

2)自定义
大驼峰式命名规则:只要遇到单词,就首字母大写,使用构造函数来创建对象时,必须要用大驼峰式命名法来命名
构造函数返回给变量的结果是object类型的

    function Car(){
        this.name = 'dache',
        this.height = 123
    }
    var car =new Car();

在这里插入图片描述

构造函数内部原理

  1. 在函数体最前面隐式var this{}的空对象
  2. 执行this.XXX = XXX;
  3. 最后会return this

包装类

原始数据类型:number,boolean,string,undefined,null
引用数据类型:object

原始值不能有属性和方法

以下三种也称为基本包装类型

var str = new String('abcd');
var num = new Number(123);
var bol = new Boolean(true);

这三种表示方式创建的和直接var创建的不一样的区别是,在没有进行计算的情况下,str,num,bol都是对象,当对num进行运算之后,她就是number类型的数据

当对原始值进行一些属性或者方法的赋值,是经历了如下过程

var num = 4;
num.len = 3;
//此时创建一个new Number(4).len = 3;    然后就把刚刚创建的直接delete了

//当下面要调用的时候,又重新创建new了一个Number类型的对象,而此时的Number(4).len是undefined
console.log(num.len);

字符串的length属性是本身就有的属性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值