首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第一节预解释、作用域、this原理

第一节预解释、作用域、this原理

作者头像
河湾欢儿
发布于 2018-09-06 09:11:36
发布于 2018-09-06 09:11:36
52100
代码可运行
举报
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
--------------------------------------------预解释----------------------------------------------------
数据类型的分类:
基本数据类型
number、string、boolean、nullundefined

引用数据类型
object:{} [] /^$/ Date
function

基本数据类型和引用数据类型的本质区别:
基本数据类型是按照值来操作的,引用数据类型是按照内存地址来操作的

思考1var num=12;
var obj={name:'张三',age:18};
function fn(){
   console.log('i love you');
}

1、当浏览器加载HTML页面的时候,首先会提供一个供全局js代码执行的环境---->全局作用域(window)
2、按照以上思考1画图,分析。(易错点:fn存储的是一个地址,代表的是当前函数的整体)

3、预解释、变量提升
   var num=12;
   1>在当前的作用域中,js代码执行之前,浏览器首先会默认的把所有带varfunction的进行提前的声明或者定义
   声明:var num;
   定义:num=12;

   2>对于带varfunction关键字的在预解释的时候操作还是不一样的
   var -->在预解释的时候只是提前的声明
   function-->在预解释的时候是声明+定义都完成了

   3>预解释只发生在当前作用域当中,例如:开始只对Window下的进行预解释,只有函数执行的时候才会对函数中
   的进行预解释

4、js中内容的分类
   栈内存:用来提供一个供js代码执行的环境--->全局作用域
   堆内存:用来存储引用数据类型的值,-->对象存储的是属性名和属性值,函数存储的是代码字符串


----------------------------------------------------作用域链-------------------------------------------------------------

如何区分私有变量和全局变量:
1、预解释的时候,在全局作用域下声明的变量是全局变量
2、在私有作用域中声明的变量(预解释的时候)和函数的形参都是私有的变量

作用域链:在私有作用域中,我们代码执行的时候遇到了一个变量,首先我们需要确定它是否为私有的变量,如果是私有的
变量,那么和外面的没有任何关系,如果不是私有的,则往当前作用域的上级作用域进行查找,如果上级作用域也没有则继续查找,一直找到window为止

当函数执行的时候,首先会形成一个新的私有的作用域,然后按照以下步骤执行:
1、如果有形参,先给形参赋值
2、进行私有作用域中的预解释
3、私有作用域中的代码从上到下执行
...
函数形成一个新的私有的作用域保护了里面的私有变量不受外界干扰,这种保护机制我们称为闭包

在全局作用域中,带var和不带var的关系?
区别:带var的可以进行预解释,所以赋值的前面执行不会报错;不带var的是不能进行预解释的,在前面会报错

关系:num2=12--->相当于给window增加了一个叫做num2的属性名,属性值是12
var num=12 相当于给全局作用域添加了一个全局变量num,不仅如此,它也相当于给window增加了一个属性名num2,属性值是12

--------------------------------------------预解释是一种毫无节操的机制---------------------------
预解释是毫无节操的一种机制
1》在预解释的时候不管条件是否成立都要把带var的进行提前声明
2》预解释的时候只预解释“=”左边的,右边的是值,不参与预解释
3》自执行函数定义的function在全局作用域下不进行预解释
4》函数体中return下面的代码虽然不执行了,但是需要预解释,return后面跟着的function 是不进行解释的
5》在js中如果变量的名字和函数的名字重复了,也算冲突
//in 判断"num"是否为window这个对象的一个属性,是返回true 不是返回false

---------------------------------------------如何查找上级作用域-------------------------------------------

如何查找当前作用域的上一级作用域?
看当前函数是在那个作用域下定义的,那么它的上级作用域就是谁,和函数在哪执行的没有任何关系

------------------------------------------关于内存的释放和作用域销毁----------------------------------
堆内存
对象数据类型或者函数数据类型在定义的时候首先会开辟一个堆内存,堆内存有一个引用地址,如果外面有变量等知道了这个地址,我们就说这个内存在占用了,就不能销毁了
    var obj1={name:'张三'};
    var obj2=obj1;
    obj1=null;
    obj2=null;

我们想让堆内存释放(垃圾回收)/销毁,只需要把所有引用它的变量值赋值为null即可,如果当前的堆内存中没有任何东西占用了,那么浏览器会在空闲的时候把它销毁
小扩展:
谷歌浏览器会每隔几毫秒会把当前的内存从头到尾看一遍,看看有没有内容有没有被占用,如果内存没有占用,就会主动清理掉
Ie 火狐通过计数器的原理,比如obj1={name:'张三'}}这个堆内存,会在浏览器的某一个位置记录当前这个堆内容有一个被占用了,计一个1,obj2=obj1,计为2(堆内存被两个占用),obj1=null,计1,obj2=null0,内容被释放了。
Ie容易计混,所以会出现泄漏的问题,详见高程3

栈内存    
1>全局作用域(浏览器天生开辟的)
当页面关闭的时候全局作用域才会销毁

2>私有作用域(只有函数执行会产生私有作用域)
 一般情况下,函数执行会形成新的私有的作用域,当私有作用域中的代码执行完成后,我们的当前作用域都会主动的进行释放和销毁
但是还是存在特殊情况的:当前私有作用域中的部分内容被作用域以外的东西占用了,那么当前作用域就不能销毁了
A、函数执行返回了一个引用数据类型的值,并且在函数的外面被一个其他的东西接收了,这种情况下一般形成的私有作用域都不会被销毁
    function fn(){
        var num=100;
        return function () {

        }
    }
    var f=fn();

B、在一个私有的作用域中给DOM元素的事件绑定方法,一般情况下我们的私有作用域都不销毁
    var odiv=document.getElementById('odiv');
    ~function(){
        odiv.onclick= function () {

        };
    }();


C、下列情况属于不立即销毁-->fn返回的函数没有被其他的东西占用,但是还需要执行一次,所以暂时不销毁,当返回的值执行完成后,浏览器会在空闲的时间把它销毁了--->不立即销毁

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

     }
 }
fn()();
//首先执行fn,返回一个小函数对应的内存地址,然后紧接着让返回小函数再执行
-----------------------------------------------this-----------------------------------------------------
this的关键字
不在函数中的this指的是window,比如:console.log(this);
我们在js中主要研究的是函数中的this。

js中的this指的是当前行为的主体。
     function 吃饭(){
        this---->张三
     }
     吃饭();
Js中context(上下文)代表的是当前执行的环境(区域)
张三在卧龙吃烤鱼  this指的是张三(当前的行为是由谁来发生的),卧龙就是上下文。
~function(){
   张三.吃饭();
}();
function sum(){
   张三.吃饭();
}
sum();
this指的是当前行为的主体,this是谁和函数在哪里定义的,和在哪里执行的没有任何关系,只和执行的主体有关系。

那么如何区分this呢?
1、函数执行的时候,看函数前面是否有”.”有的话,”.”前面是谁this就是谁,没有”.this
就是window
思考:
    function fn() {
        console.log(this);
    }
    var obj = {fn: fn};
    fn();
    obj.fn();
    function sum(){
        fn();
    }
    sum();
2、自执行函数中的this永远是window
3、给元素某一个事件绑定方法,当事件触发的时候执行对应的方法,方法中的this是当前的元素
    function fn(){
        console.log(this);
    }
    document.getElementById('odiv').onclick= fn;
    document.getElementById('odiv').onclick= function () {
        fn();
    };
4、在构造函数当中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的一个实例
5this的第5种情况:使用call/apply/bind来改变this的指向(优先级最高)


----------------------------------------------综合练习-----------------------------------------------------
综合练习题1function fn(){
        var i=10;
        return function (n) {
            console.log(n+(++i));
        }
    }
    var f=fn();
    f(10);
    f(20);
    fn()(10);
    fn()(20);


综合练习题2function fn(i){
        return function (n) {
            console.log(n+(i++));
        }
    }
    var f=fn(13);
    f(10);
    f(20);
    fn(15)(10);
fn(16)(20);


综合练习3var num = 20;
    var obj = {
        num: 30,
        fn: (function (num) {
            this.num *= 3;
            num += 15;
            console.log(num);
            var num = 45;
            return function () {
                this.num *= 4;
                num += 20;
                console.log(num);
            }
        })(num)
    };
    var fn = obj.fn;
    fn(); 
obj.fn();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.07.26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JS进阶-作用域
定义:局部作用域的意思就是,变量只能在它的代码块或者函数内部访问,而不能在外部访问,局部作用域的变量在函数或代码块执行完后会销毁,不会影响全局作用域变量。
吃猫的鱼Code
2025/02/11
3440
变量、作用域和内存问题
确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符。 4. ECMAScript中所有函数的参数都是按值传递的。 (1)传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript的概念来说,就是arguments对象中的一个元素) (2)传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部
奋飛
2019/08/15
7190
JavaScript的变量及作用域(清晰版)
JS是一门弱类型(松散型)的语言,这也就是说其天生就与众不同,独领风骚! 在讲解变量作用域之前,我们先来了解一下JS中的变量。JS中的变量与其它语言有很大的不同,由于JS变量拥有松散(不强制)的本质,从而决定了其只是一个在特定阶段保持特定类型值的名字。
用户1272076
2019/03/26
5850
「JavaScript」作用域与对象
请注意,本文编写于 2098 天前,最后修改于 174 天前,其中某些信息可能已经过时。
曼亚灿
2023/05/17
4910
「JavaScript」作用域与对象
apply/call/bind、作用域/闭包、this指向(普通,箭头,JS/Vue的this)
这里要跟this指向区分开。(这里说的作用域先简单理解为,只是变量的作用域,跟this没关系)
用户4396583
2024/10/08
1990
JavaScript——作用域
通常来说,一段程序代码中所用到的名字并不是总有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域,作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
岳泽以
2022/10/26
4340
一文带你解读​JavaScript中的变量、作用域和内存问题
基本数据类型:undefined;null;number;boolean;string;按照值访问的,可以操作保存在变量中的实际的值;
前端皮皮
2021/11/02
6690
一文带你解读​JavaScript中的变量、作用域和内存问题
从java发微javascript语法里的一些难点问题-js变量,栈区,作用域
这是一个令人诧异的结果,为什么第一个弹出框显示的是undefined,而不是1呢?这种疑惑的原理我描述如下:
周陆军博客
2023/05/07
3750
第二节单利、工厂、构造函数、原型链、call、bind、apply、sort
--------------------------------------------------单例模式---------------------------------------------------- var person1={ name:'张三', age:18 }; var person2={ name:'李四', age:19 } 对象数据类型的作用: 把描述同一个事物或的属性和方法放在一个内容空间下,起到了分组的作用,这样不同事物之间的属性即使属性名相同,
河湾欢儿
2018/09/06
1.2K0
函数表达式
定义函数的方式有两种:第一种是“函数声明”,另一种就是“函数表达式”。 “函数声明”会被提升,意味着把函数声明放在调用它的语句后面。 示例1:
奋飛
2019/08/15
5330
你不知道的javascript—作用域、闭包「建议收藏」
JavaScript 中有两个机制可以“欺骗”词法作用域:eval(..) 和 with。 前者可以对一段包 含一个或多个声明的“代码”字符串进行演算,并借此来修改已经存在的词法作用域(在 运行时)。 后者本质上是通过将一个对象的引用当作作用域来处理,将对象的属性当作作 用域中的标识符来处理,从而创建了一个新的词法作用域(同样是在运行时)。
全栈程序员站长
2022/07/20
5590
作用域及作用域链的解释说明
javascript中作用域是指变量与函数可访问的范围。作用域分为两类,一种是全局作用域,一种是局部作用域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义。局部变量是在函数体内声明而且只作用在函数体内部以及该函数体的子函数的变量。下面我们对全局作用域和局部作用域来做一个深入的理解。
OECOM
2020/07/02
1.3K0
作用域及作用域链的解释说明
前端基础-JavaScript作用域与JS代码的运行
变量的作用域是在定义时决定而不是执行时决定的,也就是说词法作用域取决于编译阶段,通过静态分析就能确定,因此词法作用域也叫做静态作用域。
cwl_java
2020/03/26
1.4K0
词法作用域
作用域共有两种主要的工作模式,第一种最为普遍,被大多数编语言所采用的词法作用域,另一种叫做动态作用域,仍有一些编程语言在使用(Bash脚本、Perl中的一些模式等)
Karl Du
2020/10/23
6210
JavaScript执行机制:变量提升、作用域链、词法作用域、块级作用域、闭包和this
所以,JavaScript是ArkTS的基础,本文就来介绍一下JavaScript执行机制的一些核心概念。
陆业聪
2024/07/23
2750
JavaScript执行机制:变量提升、作用域链、词法作用域、块级作用域、闭包和this
JavaScript高级核心知识精要:从作用域到对象高级应用​
本质上是底层的变量查找机制。在函数被执行时,会优先查找当前函数作用域中的变量,如果没有,则依次逐级查找父级作用域直到全局作用域。
VyrnSynx
2025/07/18
1020
JavaScript中的作用域和作用域链
作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。可能这两句话并不好理解,我们先来看个例子:
刘亦枫
2020/03/19
2.6K0
JavaScript中的作用域和作用域链
关于JavaScript中的闭包及应用场景
先来看一下关于闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
用户1272076
2019/03/26
9290
深入理解作用域和闭包
JavaScript中的变量是松散类型的,没有规则定义它必须包含什么数据类型,它的值和数据类型在执行期间是可以改变的。
神奇的程序员
2022/04/10
6250
深入理解作用域和闭包
js 函数作用域与this 的指向实例 原
函数的定义分为2种,(1)直接定义-window 下,内部定义;(2)对象的方法(或对象原型的方法),下面的函数fn1与fn2 是直接定义的函数, doFunction是对象定义的方法,这2种情况使用name时 name来自相应的域
tianyawhl
2019/04/04
8730
相关推荐
JS进阶-作用域
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档