简体   繁体   English

原型注入,Google Maps API

[英]Prototype injection, google maps api

I need to catch the event of getting back suggestions for google maps autocomplete . 我需要赶上找回有关Google地图自动填充建议的事件。 I know it is undocumented, but doing some research I found that it could be down via some prototype hacking. 我知道它没有记录,但是经过一些研究,我发现它可能是由于原型黑客入侵而关闭的。

<input type='text' id='myInput'>
<script src="http://maps.google.com/maps/api/js?libraries=places&amp;sensor=false&amp;language=en-EN"></script>
<script>
function catcher(key) { console.log(key); }

function MyProto() {}
MyProto.prototype = new google.maps.MVCObject();
MyProto.prototype.changed = catcher;

var gAuto = new google.maps.places.Autocomplete(
    document.getElementById('myInput'), ['geocode']);

// one of two should be commented

//gAuto.__proto__.__proto__.changed = catcher; // every key, including 'predictions'

gAuto.__proto__.__proto__ = MyProto.prototype; // only 'types', '0', and 'place' when selected
</script>

JSFiddle link: http://jsfiddle.net/agentcooper/hRyTF/ (check the console) JSFiddle链接: http : //jsfiddle.net/agentcooper/hRyTF/ (检查控制台)

Check the last two lines. 检查最后两行。 When setting 'changed' function directly on MVCObject prototype (first one, commented), everything works great and I can catch key 'predictions' in the 'catcher' function. 当直接在MVCObject原型上设置“ changed”功能时(第一个,已注释),一切正常,我可以在“ catcher”功能中捕获关键的“预测”。 The problem is that catcher needs to be different if, for example, I need to have two instances of autocomplete on my page. 问题是,例如,如果我需要在页面上有两个自动完成实例,那么捕手就必须有所不同。 So when I'm trying to inject custom object in autocomplete's prototype chain (last line) everything fails. 因此,当我尝试将自定义对象注入自动完成的原型链(最后一行)时,所有操作都会失败。 Is there any way to solve this? 有什么办法解决这个问题?

EDIT: working version , thanks to Sajid :-) 编辑: 工作版本 ,感谢萨吉德:-)

UPDATE: Completed the code , maybe it will be helpful to anyone 更新: 完成了代码 ,也许对任何人都有帮助

In the second line, you are replacing the entire prototype of the MVC object with an instance of the MVC object, and depending on how the thing is initialized, this will likely not work at all. 在第二行中,您将用MVC对象的实例替换MVC对象的整个原型,并且根据事物的初始化方式,这可能根本无法工作。 The first like replaces one function, though in the process it completely breaks that function since you don't call its superclass version, so you are not extending, you are really clobbering. 第一个like替换了一个函数,尽管在此过程中它完全破坏了该函数,因为您没有调用它的超类版本,因此您没有扩展,实际上是在破坏。 To not clobber, you need to do: 为了不使人失望,您需要执行以下操作:

(function() {
    var oldChanged = gAuto.__proto__.__proto__.changed;

    function catcher(key) {
        // call old version, and make sure to maintain this reference correctly
        oldChanged.call(this, key);
        // do your stuff here
    }

    gAuto.__proto__.__proto__.changed = catcher;
})();

One simple solution is that each object has an idea of this mentioned above. 一个简单的解决方案是,每个对象具有一个想法this如上所述。 So changed has a reference to this , which will refer to the object being used as the caller's target (except in specific situations that are a bit out of scope here). 因此,对this的引用已changed ,该引用将引用用作调用方目标的对象(在某些情况下(此处略有超出范围)除外)。 But basically: 但基本上:

var x = new MVCObject();
x.changed('hi') // this === x

So if your two versions need to do different things, you can check which this the changed method was called from and react appropriately. 所以,如果你的两个版本需要做不同的事情,你可以检查哪些this改变的方法是从所谓的和适当的反应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM