你的位置:首页 > Java教程

[Java教程]你如何给全局对象添加toString()方法


首先,在讨论如何给所有方法window对象添加tostring方法的时候,我们先来说说window的对象继承与对象实例,以及构造函数的this指针,还有变量的提升与方法的调用方式,最终一探window对象与Window方法(函数)的处理方式。

在说window对象之前,请让我们一起写一个实例的方法暖暖身,跳水之前应该做热身动作,虽然我们不跳水,不过写代码也需要做一个热身,这样才能适应下面的高难度动作。

废话好多,裁判看不下去了,开始准备你的姿势,让我们开场就拿个满分,吓死裁判,但是看到裁判吓到自己可不好了!俺表示自娱完了,该准备一下迎接下一场,go.....。

var fun = new Object();看到这个你一定不会陌生,这个就是一个实例,相比var win = new window();其实这样就会出错,错的很明显,全局属性本身就是一个实例对象。所以我们就要写一个相对于object对象的实例的一个对象才能输出Object {},var win = new window.Object();这样就不会出错了。这个win就是一个实例,那么实例也可以简化一下,如var win = {}。

此刻,你是否在想,如此我想把全局window也写成自己的,哇哇,这个建议不错,可以一试,于是乎,我们马上就写一个能替换浏览器的全局属性,var window = {};输出一个全局的空对象,一点也没问题,但是却少了浏览器特有的属性,这个是当然,我们等会儿再说,这里留个悬念。

裁判说,你这次跳水,跳的还是一般般,给本帅的感觉是没以前标准了,于是,主帅拍拍我的肩膀,小伙子,加油!我知道这是给我打气,给我加油,我喊了一声,我里个去!老子跳的这么努力,你都看不出来吗?看天空飘来一行字:友谊的小船说翻就翻!看到楼下的观众都在看着自己,于是我装作谈定,噗通一声,一跃而下,嘛呀,你TM在逗我吗,这样就结束了。

当然了,不然我这代码写到神马时候,快凌晨一点,谁会在这里看你,速度点吧。

现在我们在实例一次,var fun = new Function();相比这个也很熟悉吧,如果你觉得哪里看到过,那么你就知道Function才是一个完整的构造函数。那么简化的函数应该怎么写呢,function fun(){};这里就是一个简写的,可扩展的构造函数,有了这个条件,你肯定在想,既然能扩展,那我是不是可以给函数加点料,让函数变得更加的灵活,于是,就有以下不同的函数书写方式,如:var koringz = function(){};看到这个,你会觉得,是不是还能再给函数加点料,var koringz = function koringz(){};看起来有点耀眼,你嘛的光环这么多,我TM怎么认识你,各种装B技能都集中在一起,能不能再牛逼点吗?老子就是想看看这几个字母能组合多少次,说组合就组合,(function(){})();一种,var koringz =(function(){})();二种,! function(){}()三种,+function(){})()四种。我眼睛不好,你还是慢点吧,我们还是慢点组合,说着说着就没了,可能我都觉得这没的也太快了。如果你觉得还有更多的,还可以继续加点料,萌萌の!

有了以上各种逼格,你还觉得这些都不够给你装逼。那么下面,我想该动动真家伙了,技巧为上,有了技巧可能会比没用技巧的逼格略胜一筹,那还等什么了,说干就干呗。

我们就定义一个window全局变量,然后给这个window对象赋予各种自定义属性,

var windows = {
  top:'window',
  local:'local',
  Window:function(){},
  Attr:function Attr(){},
  koring: koringz,
  zsg:zsg,
  tr:trs,
  wyz:weiyuzhou,
  call:cal
};

这些属性你都熟悉吧,瞧一瞧,看看有么看得顺眼,过一篇有么有记住名字。

下面我给它传递方法添加属性:

var koringz = function koringz(){   koringz.toSTR = function(){};   koringz.build = ['tostr','defined tostring’];   this.CHECKING = '1';}var zsg= function(){}var weiyuzhou = function weiyuzhou01(){}var tostr = function(){}

  koringz.prototype.util = function(){}
  koringz.prototype.util2 = function(){}
  koringz.prototype.util3 = function(){}
  koringz.prototype.util4 = {};
  koringz.prototype.util5 = {};
  koringz.prototype.util5 = ['2014-2015-2016']
  koringz.prototype.util6 = '2014-2015-2016'


有了以上这些自定义函数表达式,下面我们是否可以去实现全局的获取,如若我想马上看到效果,现在是否有些急了点,还记得我们最初承诺了什么,我要给window绑定继承和this指针,甚至加上实例。对的,下面我们就一一给这个全局对象架上各种脚架,好让window对象有更多的技能释放,小心别被这些技能雷倒了。

于是乎,我们先实例一次:var po = new window.koring();然后干什么,直接迎接技能吗,我觉得还是再蓄点能量,等会儿好一起接个大招,一个个接会很累的,还不如放一起处理得了,Good好主意,就这么定了。

那么,我们再给po定义一个变量传递var pon = po;。接着我们再给函数套上继承pon.__proto__ = po.prototype;。随后我们再看看函数的调用的时候,this指针是否改变了,继承是否也改变了。

通过console.log(window);console.log(pon.util6= po.util6);你有么有发现,window属性下面的变量定义的都提前处理了!

arguments: nullbuild: Array[2]caller: nulllength: 0name: "korings"prototype: koringstoSTR: ()tostring: ()__proto__: ()

 

还有输出util6的布尔值都为true,哇哇,好厉害呀,别太鸡冻,原来我们在koring函数内部定义的this指针的属性没有被添加进来this.CHECKING = '1',但是通过koringz定义的属性添加进来了build: Array[2]  toSTR: (),说明此时的指针改变了,是通过koringz来实现的,那么此时的this指向了哪里?顺着这个问题,我们发现this指向了其他地方,原来this指针总是指向函数名,并不会指向变量名。输出this看到结果如下:

korings {CHECKING: "1"}CHECKING: "1"__proto__: korings

This指针却能透过变量拿到prototype上的方法名。

.__proto__: korings.constructor: korings().util: ().util2: ().util3: ().util4: Object.util5: Array[1].util6: "2014-2015-2016".__proto__: Object

然而,我把koringz.checking下面绑定一个this指针,看看能不能间接拿到prototype下面的CHECKING方法。发现给变量绑定的属性不能获取到,因此,我们知道var koringz变量的对象属性是不能直接被调用的,但是var koringz变量的对象属性是可以被保存起来的。korings方法上的对象属性是可以被直接调用的,不能被直接保存,所以我们要把korings方法上的对象属性保存起来,就要在var koringz变量的对象属性上绑定一个this.属性赋予给左边的变量的对象属性上,如此即可间接通过var koringz变量的对象保存一个korings方法的参数值。因此,你可以脑洞大开,通过这个去套用很多动态数据传递,恭喜你获得一次上升的机会。

接下来,我们看看能否调用到原型上的属性,也就是变量的对象属性或是变量的方法属性,看到这个关系有点复杂,心想this就是一个函数名,那么我是否可以把变量的指针绑定到this的指针上呢,所以我就要给这个变量绑定一个this,如此koringz = this我们就可以间接的转变成直接的从变量的对象属性上拿到一个值或是一个方法,而且这时候,我们不仅能拿到变量上的对象属性,还能保存变量的对象属性的输出值和方法,并且还能在外部被调用,真的是一举多得。小伙伴们,我有点困了,我只能写这么多了。

不过么讲完,我还是速度点吧。

下面我在想如何给window对象下全部子对象添加一个tostring属性呢,我们发现浏览器的window对象都是有一个字符串的方法 被调用,于是我们也可以实现这个tostring方法,那么我们就用in来为每一个window对象添加一个方法,其实,我们也可以为每一个函数表达式添加tostring方法,只不过这样不太理想了,于是我们就用如下方法,简洁明了:

var stostr= function stostr(){}
for(var p in windows){   if(typeof windows[p] == 'function'){      windows[p].toString = stostr
   }  
}

看到输出值,每一个方法下面都有一个tostring方法:

.Attr: Attr()  .arguments: null  .caller: null  .length: 0  .name: "Attr"  .prototype: Attr  .toString: stostr()  .__proto__: ()  .<function scope>  .__proto__: ()  .<function scope>.koring: korings()  .arguments: null  .build: Array[2]  .caller: null  .length: 0  .name: "korings"  .prototype: korings  .toSTR: ()  .toString: stostr()  .__proto__: ()  .<function scope>.local: "local".top: "window"

此时,每一个方法都有一个tostring方法。是否觉得 so easy!

那么我们还要调用一次tostring方法,应该如何调用呢,对此,我觉得有了以上的基础,下面我们要给所有window对象的方法添加一个调用tostring的方法,于是我们直接调用,这个肯定是不行的,他一定是建立在this指针上,所以,我们还是回到prototype继承的方法上,我们在原来的代码基础上进行一次修改,看看能否成立,在for in语句内部,我们实现一次继承:

windows[p].prototype.tostring = function(){   return 'this is trust tostring method'}

接着我们输出二个实例的对象看看效果如何:

var cas_tr = new windows.tr();var cas_Attr = new windows.Attr();
console.log(cas_tr.tostring() + '== ' + cas_Attr.tostring());
输出results:
this is trust tostring method== this is trust tostring method

这个成立!此问题到此结束。

如果你想要扩展toString资源,可以自己去研究,网上一搜一大推的事情,我就不说这个(Object.prototype.toString)。对于我这比较懒的人,一般都是用已经扩展好的方法,直接去生成一个字符串:

var s = (Math.random()).toString(22);s.substring(2,22);return "kcb0f95b4d2832j87d17"

得到一个随机的字符串。为此我想能理解的更彻底,而且说的要不一样,我特喜欢用自己的风格去处理,有空再去整合、扩展一下toString方法。

最后我们是否说点window对象和Window函数的不同之处了,你可能已经看出来了,一个是对象一个是函数当然不同了,对的,正如你看到的,Window下面的属性没有tostring方法,所以我们就不必给Window函数下面添加字符串deep调用toString方法,不过你也可以自己去扩展。下面我想我该睡了。如果你觉得对你有用,请关注一下,谢谢大家。