zoukankan      html  css  js  c++  java
  • javascript中的this

    最近在看关于拖延症的一本书《拖拉一点也无妨》,后面得出结论是自己写博客大部分处于两种状态,心情很好和心情很不好的时候。因为正常状态下感觉写博客吧,是件很麻烦的事情,不如去看看电影看看漫画啥的。最近在看漫画《进击的巨人》和《一拳超人》,感觉是两种极端,哈哈。    

    最近在进行某个项目的重写工作,前后端都要重新构架重写,时间给了一个月。项目的现状大概是后端一个类有一万行左右,包含几十个方法。每个方法从一两百行到上千行不等,大部分方法是没有参数和返回值的,全局的操作几百个成员变量。业务需求不明确,没人能说得清,反正任务就是在不影响现有的功能的情况下重构+重写。现有的功能有啥?也没人能说得清。你说测试怎么验收通过?反正测试也说不清。

    前端也面临着同样的情况,基本上都是全局的function凑合成的,几个文件加起来也有1万+行。同样没人能说得清到底有啥东西。咱作为光荣的“接盘侠”现在就要负责处理这些留下的宝贵遗产了。前端重写+后端重写+数据库SQL性能调校。

    前端打算引入EventProxy和Seajs来重新整理了。

    好吧,闲话扯到这里,现在开始继续顺带的内容了,javascript中的this

    一、Javascript中的this

    话说javascript中的this是个变态吧,总结一下:                

    隐式的改变this的指向的方法

    1.直接用括号()调用function的方式,这时this指向的是全局对象。

    2.作为对象的方法调用,那么就是指向调用方法的对象。下面就是通过改变this来借用方法。

        function addToArray() {
            arguments.slice = Array.prototype.slice;
            var add = arguments.slice(0);
            return add.concat();
        }

    可能有些人没看明白,咱的文章习惯打破砂锅问到底嘛,再举几个例子 :

    我们知道Function类型是javascript中的顶级类型,可以定义自己的属性和方法。假如有这么一个方法

    Function.prototype.test = function () {
        console.log(this === Function.prototype)
    }

    这种写法我相信有一点js经验的人都应该见过,这样写就可以给所有的函数实例加上了test方法,可具体是怎么实现的呢?我想很多人就说不清楚了。

    上面这种写法,如果这样调用,会显示什么呢?

    Function.prototype.test()

    答案是 true !

    这没什么好奇怪的,因为此时调用test方法的的确是Function类的prototype属性的对象。但如果你想想,如果this指向的是prototype的话,那么test方法为什么会在每个函数实例中都能调用呢?

    因为我们的确不会像上面这样直接调用test方法,而是通过Function类的实例来调用test方法,这时候有东西悄悄发生了变化。没错,这就是this的指向。

    如果有人还记得我上篇文章谈谈javascript中的prototype与继承的话,就知道javascript中的对象就是一个指向prototype的指针和一个自身的属性列表

    所以作为函数类的实例,其实是通过指针的方式隐式借用了Function类的prototype属性中的所有方法。这时this指向的就不再是prototype对象,而是这个实例。

    用代码来表示,类似于

    this.test = Function.prototype.test

    这里的this指向的是函数类的实例,因此调用的时候,结果就为false。

    function myFunction(){}
    myFunction.test()

    显式的改变this的一些方法和关键字

    1.call

        function addToArray() {
            var add = Array.prototype.slice.call(arguments,0);
            return add.concat();
        }

    2.apply

        function addToArray() {
            var add = Array.prototype.slice.apply(arguments,[0]);
            return add.concat();
        }

    3.bind (ECMA Script5)

    它可以看做是call 和apply的延迟版本,如果不存在的话,可以这么实现

    简单版本

    复制代码
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (target) {
            var func = this;
    
            return function () {
                func.apply(target, arguments);
            }
        }
    }
    复制代码

    其实在ECMA Script5的规定中bind是可以预填参数的,考虑到性能的话,相对复杂一些。大部分情况下我们调用bind只是希望改变this的作用域,如果全部调用了slice和concat方法,那么性能就会相对不好。根据arguments的length不同,可以分2种绑定一共4种调用的case,在大部分情况下去获取更好的性能。

    复制代码
    if (!Function.prototype.bind) {
      (function () {
        var slice = Array.prototype.slice;
    
        Function.prototype.bind = function (target) {
          var func = this;
    
          if (arguments.length > 1) {
            var args = slice.call(arguments, 1);
    
            return function () {
              var allArgs = args;
    
              if (arguments.length > 0) {
                allArgs = args.concat(slice.call(arguments));
              }
    
              return func.apply(target, allArgs);
            };
          }
    
          return function () {
            if (arguments.length > 0) {
              return func.apply(target, arguments);
            }
    
            return func.call(target);
          };
        };
      }());
    }
    复制代码
  • 相关阅读:
    centos 挂载u盘
    如何将网站部署到tomcat根目录下
    seo工具
    mysql 1045 access denied for user********
    div 自适应宽度
    mysql 日志提示 is marked as crashed and should be repaired
    css overflow:hidden无效解决办法
    java 调用 .net webservice
    Java开发笔记(十五)短路逻辑运算的优势
    Java开发笔记(十四)几种运算符的优先级顺序
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3309825.html
Copyright © 2011-2022 走看看