js作用域的几个问题
按照《权威指南》的说法,全局的变量作用域是全局性的,在js代码中,他处处都有定义。而在函数之内声明的变量,就只有在函数体内有定义了。函数的参数也是局部变量,他们只在函数体内部有定义。在函数体内部,局部变量的优先级比同名的全局变量高。如果给一个局部变量或函数的参数声明的名字与全局变量的名字相同,那么就有效地隐藏了这个全局变量。
js没有块级作用域,,函数中声明的所有变量,无论在哪里,如for ,if等,在整个函数中他们都是有定义的。这个也叫变量提升,作用域都是在函数中。
1,对象内部的作用
1 2 3 4 5 6 | var a = 10; var AAA = function (){ console.log( this .a); } var b = {a:2,bbb:AAA}; b.bbb(); |
最后输出的是2,this指向的自己的对象。this需要牢记的是 他是自己的对象的范围。点之前的作用域,是b所以bbb()执行的是b的作用域。事实是,在方法调用中是由调用表达式自身来确定this变量的绑定。。通常,通过某个对象调用方法将查找改方法并将该对象座位该方法的接受者。
2,对象共享的问题
1 2 3 4 5 6 7 8 | var cat ={}; cat.mouse = function (){ var b= "1111" }; var dog = cat; console.log(dog); console.log(dog.mouse); dog.mouse = function (){ var b= "2222" }; dog.hat= "b" ; console.log(cat) |
Object {mouse: function} hat: "b" mouse: function (){var b="2222"} __proto__: Object function (){var b="1111"} Object {mouse: function, hat: "b"} hat: "b" mouse: function (){var b="2222"} __proto__: Object
对象赋值后,指向了同一个对象,及时改变的是第二个对象,第一个对象也跟着变。conosle.log 看到是最后结果了。引用同一个对象,大家一起变。
3,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var test= function (){ var a=1; setTimeout( function (){ console.log(a); a=2; },1000); a=3; setTimeout( function (){ console.log(a); a=4; },2000); }; test(); |
结果是3,2;
共享内存。setTimeout等异步,是取现在当时的a的值。执行第一个setTimeout的时候,a=3,已经执行了。全局的对象,同一个引用。外部变量不仅可以被访问到也可以被修改。
4,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var foo=10; var a=1; var main = function (){ //a=10; console.log(a); a=20; console.log( this .foo); this .foo=foo; console.log( this .foo); foo=1000; console.log( "111111111111" ); } var s=main(); var d= new main(); |
结果是:
1
10
10
111111111111
20
undefined
1000
111111111111
不加new 都是全局的,this指向的全局变量。所以第一个就取得是全局的值。
第二个加new 了,this.foo指向的是自己,没有定义于是就报undefined。外面a foo等是全局变量,main(),执行后,a已经变成20了,foo也变成1000了,所以值发生变化了,因为全局变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var foo=10; var a=1; var main = function (){ //a=10; console.log(a); a=20; console.log( this .foo); this .foo=foo; console.log( this .foo); foo=1000; console.log( "111111111111" ); } //var s=main(); var d= new main(); |
如果不执行第一个,结果发生变化。可以发现其实是全局变量的修改。
1
undefined
10
111111111111
5、
1 2 3 4 5 6 7 8 9 10 11 12 | var a = 10; var b = function (){ console.log( this .a); } var c = function (){ this .a = 123; var d = b; d(); } var e = new c;<br>console.log(window.a); |
1 2 3 4 5 6 7 8 9 | var a = 10; var c = function (){ this .a = 123; var d = function (){ console.log( this .a); }; d(); } var e = new c; |
结果是10。 window.a其实就是全局的那个a。this指的是在一个函数内部调用它的上下文关系,单独的一个函数了。var d单独的一个函数,他的this.a指向的是全局的了,没有作用域,就是全局了。
1 2 3 4 5 6 7 8 9 10 11 12 | var a = 10; var b = function (){ console.log( this .a); } var c = function (){ this .a = 123; this .d = b; this .d(); } var e = new c; |
结果是123,如果this.d(),写成d(),会报错 d is not defined。 this.d 将d的后面的this变成了c这个函数了。点执行方法,作用域是点之前的。
1 2 3 4 5 6 7 8 9 | var a = 10; var c = function (){ this .a = 123; this .d = function (){ console.log(a); }; this .d(); } var e = new c; |
结果是10。
1 2 3 4 5 6 7 8 9 10 | var a = "aaaa" ; var c = function (){ this .a = "bbbb" ; this .d = function (){ console.log(a); }; // this.d(); } var e = new c(); console.log(e.d()) |
结果是:
aaaa
undefined
在 JavaScript 中,上下文对象就是 this 指针,即被调用函数所处的环境。上下文对象 的作用是在一个函数内部引用调用它的对象本身。
在 JavaScript 中,本质上,函数类型的变量是指向这个函数实体的一个引用,在引用之 间赋值不会对对象产生复制行为。我们可以通过函数的任何一个引用调用这个函数,不同之处仅仅在于上下文。
仔细观察上面的例子,使用不同的引用来调用同一个函数时,this 指针永远是这个引用所属的对象.
函数作用域的嵌套关系是定义时决定的,而不是调用时决定的,也就 是说,JavaScript 的作用域是静态作用域,又叫词法作用域,这是因为作用域的嵌套关系可 以在语法分析时确定,而不必等到运行时确定
基础类型是通过传值来操作,而引用类型则是通过传址来操作的
数字和布尔类型是基础类型,因为它们是由很小的,固定数目字节组成。
对象是引用类型。数组和函数,是对象的特殊类型,也是引用类型。由于对象的没有固定大小,所以无法通过传值。
需要注意的是,如果函数用新的一个对象或者数组覆盖这个引用,那么这一修改在外部是不可见的。或者说,对象和数组是用传值的方式来传递的,只不过这个值是一个引用,而不是本身。
参考 http://www.cnblogs.com/joe2014/archive/2014/06/28/3813919.html
字符串类型
前面看了这么多类型,一直都没有介绍字符串类型,它不好直接分为基础类型和引用类型,因为字符串是一种任意的长度,看上去应该是引用类型,可是他却不是对象,所以也不可作为引用类型。
类型 |
复制 |
传递 |
比较 |
数字 | 传值 | 传值 | 传值 |
布尔 | 传值 | 传值 | 传值 |
字符串 | 不可变 | 不可变 | 传值 |
对象 | 传址 | 传址 |
传址
|
参考:http://www.cnblogs.com/bennman/archive/2013/09/08/3309024.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构