深究js(三)——变量

2024-03-15 16:48
文章标签 js 变量 深究

本文主要是介绍深究js(三)——变量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、变量声明

    在JavaScript中,使用一个变量之前应当声明一个变量,变量是使用关键字var来声明的。如:

var a;
    声明了一个变量未赋值的时候,默认值为underfined。可能你会说,我没有用var声明,也可以直接用这个数也可以啊,如:

a = 10
alert(a)
    这里事先没有声明变量a,而是直接给变量a赋值,当运行的时候也是没问题,乍一看好像问题不大,其实还是有一些问题的。这样子未声明一个变量去使用这个变量的话,这个变量是全局变量,是JavaScript通过在全局对象中创建出来的一个同名属性,但是这是一个不好的习惯,会造成很多bug,在严格模式和ECMAScript标准中是严令禁止这样做的。在eslint中,如果声明了一个变量但是没有赋值也是会报错的。


二、变量作用域

   一个变量的作用域是程序源代码中定义这个变量的区域。全局对象拥有全局作用域,在JavaScript的任何地方都是有定义的,而在函数内声明的变量只在函数内有定义,他们称为局部变量。函数的参数也是一个局部变量,只在函数体内有定义。

    在函数体内,局部变量的优先级高于同名的全局 变量,也就是说当在函数体内局部变量与全局变量同名,全局变量会被局部变量所遮盖掉。如:

var a = 'a'
function ha () {var a = 'b'
    return a
}
alert(ha())    //返回的是b
    局部变量一定要用var声明,如果函数体内的一个变量没有用var声明,而函数体外恰好有这个同名变量,这个时候就能体现出这个陋习的bug了。如:

function ha () {a = 'b'
    return a
}
ha()
alert(a)    //返回的是b
    全局变量a在函数体内被修改了,所以声明变量的时候一定要加一个var,防止出现未知的bug。当声明了一个JavaScript全局变量的时候,实际上是定义了全局对象的一个属性。当使用var来声明变量时,这个创建的属性是不可配置的,也就是说这个变量是无法通过delete运算符删除的,但是没用var声明变量时,变量可以被delete删除。


三、声明提前和函数作用域 

    在java中,花括号内的每一段代码都有各自的作用域,并且变量在声明它们的作用域之外是不可见的,这称之为块级作用域。但是在JavaScript中是没有块级作用域这个概念,取而代之的是函数作用域。在函数作用域里面,变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。如:

var o = new Date()
function test(o) {var i = 0
    if (typeof o == 'object') {var j = 0
        for (var k = 0;k < 10; k++) {console.log(k)}console.log(k)}console.log(j)
}
test(o)
    第一个输出从0到9,第二个输出的是10,第三个输出的是0。用过java的可能会对这个结果产生一些疑问,为什么k和j的值都能够输出来呢?是因为在test()函数内,i,j,k都在同一个函数作用域内,在函数作用域内变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。也就是说,i,j,k变量声明提前了,这样的话上述的代码等价于:

var o = new Date()
function test(o) {var i = 0
    var kvar jif (typeof o == 'object') {j = 0
        for (k = 0;k < 10; k++) {console.log(k)}console.log(k)}console.log(j)
}
test(o)
    JavaScript的函数作用域指的是在函数内声明的所有变量在函数体内始终可见的,这样子会让变量在声明之前已经可用,这一特性被称为声明提前。一个典型的例子如下所示:

var a = 'a'
function aa() {console.log(a)var a = 'b'
    console.log(a)
}
aa()
    如果你以为第一个输出的是a就大错特错了,第一个输出的是underfined,第二个输出的是b。首先在JavaScript里,在函数体内定义一个变量是在整个函数内可见,也就是说即使你的变量声明放在最后写,它仍然会将这个变量声明提前。并且局部变量的优先级比全局变量的优先级高,在给变量a赋值之前它的初始值为underfined,所以上述的代码可以理解成这样:

var a = 'a'
function aa() {var aconsole.log(a)a = 'b'
    console.log(a)
}
aa()
    在JavaScript编程中,如果在函数体内声明变量,尽量的把变量放在前面,这样方便查找变量,也能真实的反映变量的作用域。


四、作用域链

    作用域链是一个对象列表或者链表,这组对象定义了代码中“作用域中”的变。当JavaScript需要查找变量x的值的时候,它会从链中的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果没有则一直找,当作用域链上没有任何一个对象含有属性x,则会报一个引用错误的异常。下面有一个例子是举例说明作用域链的:

var x =1
function a() {var y = 2
    function aa() {var z = 3
        console.log(x + y + z)}aa()
}
a()

    当函数执行到aa()方法里的console,它会找aa()里面有没有变量x和y,没有的话,则向上一级去a()方法里面查找变量x和y,a()方法里有y但是没有x,于是继续向上查找,找到了x,所以输出的结果是6。下面有另一个常见的例子更能说明这个问题:

var a = []
for(var i = 0; i < 3; i ++ ) {a[i] = function () {console.log(i)}
}
a[0]()
a[1]()
a[2]()
    你认为会输出什么?如果你以为输出的是0,1,2其实就是大错特错了。因为在这个匿名函数里,根本就没有声明i这个变量,所以就通过作用域链来向上查找变量i,恰逢此时循环已经遍历完成,最终的i是等于3,所以最后这三个输出的结果为3。有关作用域链这个东西在《JavaScript权威指南》里并没有过多的讲述,由于本人水平有限可能讲的不够详细,特意推荐这两个不错的推文,都是讲作用域链的,作用域链对理解闭包和with语句有很大的帮助,下面就贴上那两个地址给大家参考。

http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

http://www.cnblogs.com/dolphinX/p/3280876.html



这篇关于深究js(三)——变量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812617

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

变量与命名

引言         在前两个课时中,我们已经了解了 Python 程序的基本结构,学习了如何正确地使用缩进来组织代码,并且知道了注释的重要性。现在我们将进一步深入到 Python 编程的核心——变量与命名。变量是我们存储数据的主要方式,而合理的命名则有助于提高代码的可读性和可维护性。 变量的概念与使用         在 Python 中,变量是一种用来存储数据值的标识符。创建变量很简单,

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>

js react 笔记 2

起因, 目的: 记录一些 js, react, css 1. 生成一个随机的 uuid // 需要先安装 crypto 模块const { randomUUID } = require('crypto');const uuid = randomUUID();console.log(uuid); // 输出类似 '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

uuid.js 使用

相关代码 import { NIL } from "uuid";/** 验证UUID* 为空 则返回 false* @param uuid* @returns {boolean}*/export function MyUUIDValidate(uuid: any): boolean {if (typeof uuid === "string" && uuid !== NIL) { //uuid