关于window.name属性的详解与扩展

529 阅读4分钟

关于window.name属性的详解与扩展

对于一个刚入门的前端小白,总是会遇到一些奇奇怪怪的小bug,今天在学习js作用域链的时候,就遇到了一个一脸懵逼的小bug:

console.log(a)
var a = 'word'

console.log(name)
var name = 'hello'

这里大家都知道如果使用var声明变量,会产生变量提升,且仅提升变量的声明,不会提升变量的赋值;大家思考一下上面的代码会输出什么呢?

  • 当第一次打开浏览器时:

image-20230914092128892.png

  • 这时如果你再次刷新浏览器:

image-20230914092144101.png

这是为什么呢?

对于基础扎实的同学应该已经想到了,name好像是浏览器顶级对象window的属性,那么大家对它了解多少呢?这里我们来详细学习一下window.name吧!

首先,上述问题如果你改为以下代码便没有以上问题了。

image-20230914093342430.png

这里你使用const声明也是一样的,这是因为var在全局作用域下声明name变量,实际是成为了window的属性,而let与const会形成自己的作用域,所以要先声明再使用,提前调用便会报错。

好的,我们把目光重新放到window.name身上吧。我们先来验证它到底是什么?

image-20230914094830155.png

当我们展开window时:

image-20230914094916550.png

至此我们可以确定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>
    
    
  • 当我们从第一个页面跳转到第二个页面时,第二个页面如下:

image-20230914100354925.png

  • 这里我们就可以看出,第一个网页的a标签通过target属性将值赋值给第二个窗口的name属性,这样第二个网页的name属性就有值了。

  • 还有一点需要注意,如果给name赋值,那么 window.name 会调用 类似于 toString 的方法将赋给它的值转换成对应的字符串表示。为什么说类似呢?因为toString的可以将Symbol数据类型转字符串,但它不行。

image-20230914102939895.png

到这里,我们已经认识了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属性跳转到指定页面。
  1. 第一个页面(借助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>
    
    
  2. 第二个页面(空页面 localhost域名下)

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>页面二</title>
    </head>
    <body>
    </body>
    </html>
    
  3. 第三个页面(要传递的数据,且与上面两个页面的域名不一样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>
    
    

这样我们就可以在页面一中获取到其他域名下的数据了。这个跨域方式可能并不常用,大家作为一个了解就可以了;好的今天的分享就到这了,前端的学习道路还很漫长,大家一起加油吧。