关于window.name属性的详解与扩展
对于一个刚入门的前端小白,总是会遇到一些奇奇怪怪的小bug,今天在学习js作用域链的时候,就遇到了一个一脸懵逼的小bug:
console.log(a)
var a = 'word'
console.log(name)
var name = 'hello'
这里大家都知道如果使用var声明变量,会产生变量提升,且仅提升变量的声明,不会提升变量的赋值;大家思考一下上面的代码会输出什么呢?
- 当第一次打开浏览器时:
- 这时如果你再次刷新浏览器:
这是为什么呢?
对于基础扎实的同学应该已经想到了,name好像是浏览器顶级对象window的属性,那么大家对它了解多少呢?这里我们来详细学习一下window.name吧!
首先,上述问题如果你改为以下代码便没有以上问题了。
这里你使用const声明也是一样的,这是因为var在全局作用域下声明name变量,实际是成为了window的属性,而let与const会形成自己的作用域,所以要先声明再使用,提前调用便会报错。
好的,我们把目光重新放到window.name身上吧。我们先来验证它到底是什么?
当我们展开window时:
至此我们可以确定window.name在第一次打开浏览器时是一个空字符串,到这里我们就了解了上面的bug产生的原因,我们第一次打印name时,实际上打印的是window.name这个空字符串,而紧接着我们又给其重新赋值,这个值就存储到了window.name中了,当我们再次刷新页面时,window.name并不会清除,所以当页面打印name时就有了值。 这里我查阅了相关文档;对window.name的描述更加详细的是:window.name直译过来是窗口名字,主要用于为超链接和表单设置目标(targets),这是什么意思呢,我们来做个案例
-
第一个页面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>demo1</title> </head> <body> <a href="./demo2.html" target="hello world">跳转</a> </body> </html> -
第二个页面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>demo2</title> <script> document.write( window.name + "<br>" + name ) </script> </head> <body> </body> </html> -
当我们从第一个页面跳转到第二个页面时,第二个页面如下:
-
这里我们就可以看出,第一个网页的a标签通过target属性将值赋值给第二个窗口的name属性,这样第二个网页的name属性就有值了。
-
还有一点需要注意,如果给name赋值,那么 window.name 会调用 类似于 toString 的方法将赋给它的值转换成对应的字符串表示。为什么说类似呢?因为toString的可以将Symbol数据类型转字符串,但它不行。
到这里,我们已经认识了window.name的属性了,来看看大家掌握的怎么样吧,下面这段代码会打印什么呢?
var name = 123
let arr = [123]
console.log(+arr)
console.log(name + 123 + arr)
接下来我们扩展一下window.name的一个使用场景。
- 这里提一下 window.open( strUrl , strWindowName , [strWindowFeatures] ) 的第二值也是可以给新窗口设置window.name;
- 用 window.name 实现跨域,是利用他的一个特点,就是在一个页面载入的其他页面将共享一个window.name,其他页面都有对其的读写权限,即使其他页面载入新页面,其window.name也不变。从上面的a标签跳转我们验证了这一特点,下面我们使用window.open,携带window.name属性跳转到指定页面。
-
第一个页面(借助iframe配置跨域 localhost域名下)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>页面一</title> </head> <body> <h1>页面一</h1> <script> var iframe = document.createElement('iframe');//工具人 iframe.style.display = "none";//工具人隐藏在背后默默付出 var flag = false; iframe.onload = function () { if ( flag ) { var data = iframe.contentWindow.name;//contentWindow.name可以拿到iframe的窗口name值 console.log(data); iframe.contentWindow.close();//关闭隐藏的页面 document.body.removeChild(iframe);//删除隐藏的页面 } else { flag = true; iframe.contentWindow.location = 'http://localhost/demo2.html';//这里因为浏览器同源策略,需要将链接改成与页面一同源的页面(也就是页面二),这里会再次触发load事件 } } iframe.src = 'http://data/data.html';//跨域,这里窗口已经拿到name,所以上面更换地址后name的值依旧存在 document.body.appendChild(iframe); </script> </body> </html> -
第二个页面(空页面 localhost域名下)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>页面二</title> </head> <body> </body> </html> -
第三个页面(要传递的数据,且与上面两个页面的域名不一样data域名下)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>data</title> </head> <body> <h1>数据</h1> <script> window.name = '{data:"数据"}';//将数据存到window.name里 </script> </body> </html>
这样我们就可以在页面一中获取到其他域名下的数据了。这个跨域方式可能并不常用,大家作为一个了解就可以了;好的今天的分享就到这了,前端的学习道路还很漫长,大家一起加油吧。