zoukankan      html  css  js  c++  java
  • 函数也有上下文与call与apply的区别

      原来一直以为call和apply只是传递参数的形式不同:call使用参数列表,apply使用参数数组。但在跨窗口使用时,发现函数其中在 new 时,会传递上下文到函数中。于是函数实例也便有了上下文。

      在我的这个测试中,也发现了 call 和 apply 的区别:call可以跨窗口调用传参调用函数,apply跨窗口调用有参数函数时出错。下面是测试,打开父窗口时,使用window.open打开一个子窗口,然后在子窗口中调用父窗口的函数以及对象:

    父窗口:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
        
    <title>Untitled</title>
            
    <script type="text/javascript">
            
    function Person(name)
            {
                
    this.name = name;
                
                
    this.getName = function()
                {
                    
    return this.name;
                }
                
                
    var sex = '';
                
    this.getSex = function()
                {
                    
    return sex;
                }
                
                
    this.say = function(what)
                {
                    
    return '[' + window.$room + '/' + room + ']' + '' + this.getName() + ',' +  this.getSex() + ' ' + what;
                }
            }
            
    </script>
    </head>

    <body>

    <script type="text/javascript">
            
    //全局变量
            var room = '房间';
            window.$room 
    = '房间';
            
    var person = new window.Person('父窗口');
            alert(person.say);
            window.open(
    'test2.html''test2');
    </script>

    </body>
    </html>

    子窗口:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
        
    <HEAD>
        
    </HEAD>
        
    <body>
            
    <script type="text/javascript">
            window.alert 
    = function(msg)
            {
                document.getElementById(
    'log').innerHTML += msg + "<br/>";
            }
            
    function invoke()
            {
                
    //得到父窗口中的对象
                var obj = window.opener.person;
                
    //得到对象函数
                var sayHandle = obj.say;
                
                alert(window.opener.person.say(
    '直接调用,成功'));
                alert(sayHandle.call(window.opener.person, 
    '直接使用全路径引用,使用 call 传参调用,成功'));
                alert(sayHandle.call(obj, 
    '使用对象引用,使用 call 传参调用,成功'));
                
    try
                {
                    alert(sayHandle.apply(window.opener.person, [
    '这里使用 apply 失败']));
                }
                
    catch(e)
                {
                    alert(e);
                }
                
    try
                {
                    alert(sayHandle.apply(obj, [
    '这里使用 apply 失败']));
                }
                
    catch(e)
                {
                    alert(e);
                }
                
            }
            
            
    //全局变量
            var room = "子房间";
            window.$room 
    = '子房间';

            
    function invokeSelf()
            {
                
    //得到父窗口中的函数定义
                eval(window.opener.Person.toString());
                
                
    //在全局中新建对象
                window.person = new Person('子窗口');
                
                
    //得到对象引用
                var obj = window.person;
                
    //得到函数引用
                var sayHandle = obj.say;
                
                alert(window.person.say(
    '直接调用成功'));
                alert(sayHandle.call(window.person, 
    '直接使用全路径引用,使用 call 传参调用,成功'));
                alert(sayHandle.call(obj, 
    '使用对象引用,使用 call 传参调用,成功'));
                alert(sayHandle.apply(window.person, [
    '直接使用全路径引用,使用 apply 传参调用,成功']));
                
    //使用对象引用,使用 apply 传参调用,成功
                alert(sayHandle.apply(obj, ['使用对象引用,使用 apply 传参调用,成功']));
                
                
    //使用父窗口的函数, 使用本窗口数据
                var sayHandle = window.opener.person.say;
                
                alert(sayHandle.call(window.person, 
    '直接使用全路径引用,使用 call 传参调用 父窗口的函数 ,成功但结果错'));
                alert(sayHandle.call(obj, 
    '使用对象引用,使用 call 传参调用 父窗口的函数 ,成功但结果错'));
                
    try
                {
                    alert(sayHandle.apply(window.person, [
    '直接使用全路径引用,使用 apply 传参调用 父窗口的函数,失败']));
                }
                
    catch(e)
                {
                    alert(e);
                }
                
    try
                {
                    alert(sayHandle.apply(obj, [
    '使用对象引用,使用 apply 传参调用 父窗口的函数 ,失败']));
                }
                
    catch(e)
                {
                    alert(e);
                }
            }        
            
    </script>
            
    <href="javascript:invoke();invokeSelf()">调用父窗口函数</a>
            
            
    <div id="log"></div>
        
    </body>
    </html>

    下面是运行结果:

    Code
  • 相关阅读:
    vue :调用子组件 ,watch props 时,监听不到
    table 》 td 超出内容过长显示...
    kendo 服务端排序
    Highcharts的基本属性和方法详解
    使用vue element table 自定义列模版
    vue 结合JQ ajax 作用域会改变
    实用的javascript 简写--读后感~
    【iOS】iOS13新增的暗黑模式(Dark Mode)
    【iOS】iOS13后新增的Scene Delegate和不使用工程自带的Main.storyboard
    【iOS】检测项目中是否包含UIWebView
  • 原文地址:https://www.cnblogs.com/evlon/p/1592078.html
Copyright © 2011-2022 走看看