[js]02js预解释-作用域-this关键字

来源:互联网 发布:2017年双十一实时数据 编辑:程序博客网 时间:2024/05/13 07:04

js预解释 作用域 this关键字

  • 预解释
  • 作用域
  • this

如何查找当前作用域的上一级作用域?

  • 看当前函数是在哪个作用域下定义的,那么它的上级作用于就是谁
  • 和函数在哪执行的没任何关系
var  num = 12;function fn() {    var num = 120;    return function () {        console.log(num);    }    var f = fn();    f(); // 上一级作用于是A    ~function () {        var num = 1200;        f(); // 上一级作用于是A,和在哪里执行的无关    }()}

image

函数的预解释:

自执行函数不进行预解释

js内存的释放

image

堆内存释放

  • 堆内存的释放

    • 对象或者
    • 函数 定义时候都会开辟堆内存
  • 规则

    • 对象数据类型或者函数数据类型在定义的时候,首先会开辟一个队内存,堆内存有一个引用地址,如果外边有变量等知道了这个地址,我们就说这个内存被占用了,就不能被销毁了.
    • 我们想让堆内存释放/销毁,只需要把所有引用它的变量值赋值给null即可.如果当亲啊堆内存没有被任何东西占用,则浏览器在空闲的时候把他销毁i
var obj = {name:"maotai"};var obj2 = obj;

image

obj = null;obj2 = null;

栈内存的释放

  • 全局作用域:只有当页面的关闭销毁
  • 私有作用域: 只有函数执行时候会产生私有的作用域.
    • 以下是代码块,不会开辟私有作用域.
for(){}if(){}switch(){}
  • 一般情况下,函数执行会形成一个新的私有作用域,当私有作用域中的代码执行完成后,我们当前的作用域都会主动的进行释放和销毁.

  • 特殊情况:

    • 当前私有作用域中的部分内存被作用域意外的东西占用了,那么当前这个作用域就不能被销毁了.
      image

    • 特殊情况1:
      函数执行返回了一个引用数据类型的值,并且在函数在外边被一个其他的东西接受,这总请客下一般形成的私有作用域不会被销毁.

function fn() {    var num = 1000;    return function () {    }}var f = fn() //fn执行形成的私有作用域就不能被销毁了
  • 特殊情况2
    在一个私有作用域中给DOM元素的事件绑定方法,一般情况下,我们的私有作用域都不能销毁
var oDiv = document.getElementById("div1");~function () {    Odiv.onclick = function () {    }}(); //当前私有作用域不能被销毁

ps: 通过getelement取得的是object类型数据

image

  • 特殊情况3:

不立即销毁–>fn返回函数没有被其他东西调用,但是还需要执行一次呢,所以暂时不小hi,当返回值执行完成后,浏览器会在空闲时候把他销毁.

function fn() {    var num = 100;    return function () {    }}fn()();

作用域实战题

function fn () {    var i = 10;    return function(n){        console.log(n+(++i));    }}var f = fn();f(10); //21f(20);//32fn()(10);//21fn()(20);//31

![image]http://ww1.sinaimg.cn/large/9e792b8fgy1fiez0429g1j213e0gjajx)

image

另外一道题

function fn (i) {    return function(n){        console.log(n+(i++));    }}var f = fn(13);f(12); //25f(14);//28fn(15)(12);//27fn(16)(13);//29

使用闭包作用域的方式实现选项卡循环绑定事件的处理

this关键字

console.log(this) //window
  • js中this代表的是当前行为执行主体, 我们主要研究函数中的this
function 吃饭(){    this-->张三}张三.吃饭()
  • js中context代表当前行为执行的环境或区域.

    • 张三在沙县小吃 吃蛋炒饼, this是张三, context是沙县小吃.
  • this是谁和函数在哪定义的 和 在哪里执行的都没任何关系.

~function(){    张三.吃饭();}

如何区分this?

  • 1,函数执行,首先看函数名前面是否有 “.”,有的话”.”是谁,this就是谁, 没有的话,this就是window
function fn() {    console.log(this);}var obj = {fn:fn};fn();// this-->windowobj.fn();// this-->obj
function sum(){    fn(); // this-->window}sum();
function fn() {    console.log(this)}var oo = {   // sum里的this是oo    sum: function () {        fn(); // this--> window    }}oo.sum();
  • 2,自执行函数中的window,永远是window
  • 3,给元素的某一个元素绑定方法,当事件触发的时候,执行对应的方法,方法中的this是当前的元素.
<div id="div1" style="width: 100px;height: 100px;background-color:green;">123213123</div><script>function fn() {    console.log(this) // this ->document.getElementById("div1")}document.getElementById("div1").onclick=fn;</script>

结果:

<div id="div1" style="width: 100px;height: 100px;background-color:green;">123213123</div>

另一个例子:

document.getElementById("div1").onclick=function(){    // this--> #div1    fn(); // this->window};

实战题

var num = 20;var obj = {    num: 30,    fn:(function (num) {        this.num*=3;        num +=15;        var num = 15;        return function () {            this.num*=4;            num+=20;            console.log(num);        }    })(num)};var fn=obj.fn;fn(); //35obj.fn(); //55console.log(window.num,obj.num) //240 120

image

案例多种方法

实现效果: 点button数字累加

image

案例:实例
实现点击自加:

1.利用全局作用域不销毁原理.把需要累加的数字定义为全局变量

    var oBtn = document.getElementById("btn");    var spanNum=document.getElementById("spanNum");    var count=0;    btn.onclick=function () {        count++;        spanNum.innerHTML=count;    }//弊端:为了防止项目中全局变量之间的冲突,我们一般是禁止使用全局变量.

2.思想:自建一个不销毁的私有作用域

~function(){}();~function(){  // 在私有作用域中给外部的一个元素对象的某一个事件绑定一个方法.    var oBtn = document.getElementById("btn");    var spanNum=document.getElementById("spanNum");    var count=0;    btn.onclick=function () {        count++;        spanNum.innerHTML=count;    }    }();

3,思想和2相同

返回一个引用类型给oBtn,则自执行函数也无法被销毁.

oBtn.onclick=(function(){    var count = 0;    return function(){        count++;        spanNum.innerHTML=count;    }})();//弊端: 占用内存

4.第三种方法:利用innerHTML的方式处理:每一次点击的时候,都先回到页面中获取值,然后累加,最后把累加的结果放回去.

oBtn.onclick=function(){    //spanNum.innerHTML=spanNum.innerHTML+1; //获取的是字符串,有问题    spanNum.innerHTML++;//自动转换,且实现自加.};//弊端: 每一次都要把页面中的内存先转换为字符串,然后累加,累加完成后重新添加回去,当重新欠佳的时候浏览器都需要重新渲染

5.利用自定义属性存储.

oBtn.count=0; //给oBtn添加属性oBtn.onclick=function(){    spanNum.innerHTML=++this.count;}