What's the point of accessing element.innerText without doing anything else in some interesting JavaScript code?

huangapple go评论61阅读模式
英文:

What's the point of accessing element.innerText without doing anything else in some interesting JavaScript code?

问题

我遇到了这个名为VWO的第三方分析代码,其中嵌入的脚本很有趣,官方文档在这里:https://help.vwo.com/hc/en-us/articles/360021306233-Volusion

因此,他们文档中有趣的代码如下:

           load: function(a) {
               var b = d.createElement('script');
               b.src = a;
               b.type = 'text/javascript';
               b.innerText;
               b.onerror = function() {
                   _vwo_code.finish();
               };
               d.getElementsByTagName('head')[0].appendChild(b);
           },

这是他们嵌入的代码的一部分;我注意到b.innerText 什么也没有做,我很好奇那里到底发生了什么。这是一种浏览器工程级别的技巧吗?

我知道某些代码会导致浏览器强制重绘,但似乎并非如此。

有人有任何想法吗?

英文:

I came across this third-party analysis code known as VWO, the embedded script is interesting, and the official documentation is available here: https://help.vwo.com/hc/en-us/articles/360021306233-Volusion

Thus the interesting code in their documentation is as follows:

           load: function(a) {
               var b = d.createElement('script');
               b.src = a;
               b.type = 'text/javascript';
               b.innerText;
               b.onerror = function() {
                   _vwo_code.finish();
               };
               d.getElementsByTagName('head')[0].appendChild(b);
           },

Here is a section of their embedded code; I saw that b.innerText accomplished nothing, and I was curious what occurred exactly there. Is this a browser engineering level trick?

I'm aware that some kind of code will cause the browser to force paint, but this doesn't appear to be the case.

Anybody have any ideas?

答案1

得分: 3

这是以前添加的,以支持IE浏览器。我们将重新评估这一点,看看是否仍然需要支持任何可用的浏览器版本。

英文:

This was added to support the IE browser in the past. We will re-evaluate this to see if this is still required for any of the available browser versions.

答案2

得分: 2

你忘记在代码中包含一些非常重要的细节:

         load: function(a) {
               var b = d.createElement('script');
               b.src = a;
               b.type = 'text/javascript';
               b.innerText;
               b.onerror = function() {
                   _vwo_code.finish();
               };
               d.getElementsByTagName('head')[0].appendChild(b);
           },
           init: function() {
               settings_timer = setTimeout('_vwo_code.finish()', settings_tolerance);
               var a = d.createElement('style'),
                   b = 'body{opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important;}',
                   h = d.getElementsByTagName('head')[0];
               a.setAttribute('id', '_vis_opt_path_hides');
               a.setAttribute('type', 'text/css');
               if (a.styleSheet) a.styleSheet.cssText = b;
               else a.appendChild(d.createTextNode(b));
               h.appendChild(a);
               this.load('//dev.visualwebsiteoptimizer.com/j.php?a=' + account_id + '&u=' + encodeURIComponent(d.URL) + '&r=' + Math.random());
               return settings_timer;
           }

在调用load方法之前,他们插入了一个<style>元素。

根据这个<style>的内容,我怀疑(没有检查导入的JS),他们实际上想在执行脚本之前触发回流,以便body { opacity: 0 }规则在脚本触发此CSS属性的过渡之前(我猜再次)计算。如果不这样做,渲染器将只看到最后设置的值,并且无法从中进行过渡。

为什么他们没有在<script>添加到DOM之后触发这个操作?
有可能在下一个绘制帧之前执行脚本,因此在下一个自动回流之前执行脚本。

为什么他们没有直接将强制回流集成到脚本中?
不清楚。

但是

正如Teemu指出的那样,他们在b上调用innerText getter,但b尚未在DOM中,因此不会触发回流。他们可能本来想调用另一个元素的(例如document.body)getter,但这段代码实际上什么都不会做。

英文:

You forgot to include some very important details on the code:

         load: function(a) {
               var b = d.createElement(&#39;script&#39;);
               b.src = a;
               b.type = &#39;text/javascript&#39;;
               b.innerText;
               b.onerror = function() {
                   _vwo_code.finish();
               };
               d.getElementsByTagName(&#39;head&#39;)[0].appendChild(b);
           },
           init: function() {
               settings_timer = setTimeout(&#39;_vwo_code.finish()&#39;, settings_tolerance);
               var a = d.createElement(&#39;style&#39;),
                   b = &#39;body{opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important;}&#39;,
                   h = d.getElementsByTagName(&#39;head&#39;)[0];
               a.setAttribute(&#39;id&#39;, &#39;_vis_opt_path_hides&#39;);
               a.setAttribute(&#39;type&#39;, &#39;text/css&#39;);
               if (a.styleSheet) a.styleSheet.cssText = b;
               else a.appendChild(d.createTextNode(b));
               h.appendChild(a);
               this.load(&#39;//dev.visualwebsiteoptimizer.com/j.php?a=&#39; + account_id + &#39;&amp;u=&#39; + encodeURIComponent(d.URL) + &#39;&amp;r=&#39; + Math.random());
               return settings_timer;
           }

Before they call this load method, they do insert a &lt;style&gt; element.

Given this &lt;style&gt;'s content, I'd suspect (didn't check the imported JS) they actually want to trigger a reflow before the script gets executed so that the body { opacity: 0 } rule is computed before (I guess once again), the script triggers a transition on this CSS property. Failing to do so, the renderer would only see the last value set and wouldn't have anything to transition from.

Why did they not trigger this after the &lt;script&gt; is in the DOM?
There could be a risk of having the script executed before the next painting frame and hence before the next automatic reflow.

Why did they not integrate the forced reflow inside the script directly?
No idea.

BUT

There is a but, as spotted by Teemu, they call the innerText getter on b, which isn't in the DOM yet and thus wouldn't trigger a reflow. They probably meant to call another element's one (e.g document.body), but this code will actually do nothing.

huangapple
  • 本文由 发表于 2023年2月24日 15:38:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553750.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定