首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >calc()回退脚本

calc()回退脚本
EN

Code Review用户
提问于 2012-08-07 00:50:07
回答 3查看 4.5K关注 0票数 3

我为相当新的CSS calc()规则编写了一个故障回退。它工作很好,但我想在生产环境中使用它,并希望得到反馈。请推荐任何关于奇怪/错误代码、可能的优化或减少代码大小的方法。

代码语言:javascript
复制
// CSS calc() replacement
function calcfailback(){
   var d = document.createElement('div');
   var _body = document.getElementsByTagName('body') [0];
   _body.appendChild(d);
   d.style.visibility = 'hidden';
   d.style.width = "-webkit-calc(10px)";
   d.style.width = "-o-calc(10px)";  
   d.style.width = "-moz-calc(10px)"; 
   d.style.width = "calc(10px)";   
   var newwidth = d.offsetWidth;
   if (newwidth == "10"){}
   else{
      function resize(){
         document.getElementById('content').style.height = window.innerHeight - 40 + 'px';
         document.getElementById('content').style.width = window.innerWidth - 300 +'px';
         document.getElementById('sidebar').style.height = window.innerHeight - 40 + 'px';
      };
      resize();
      window.onresize = function (){
         resize();
      }
   };
   _body.removeChild(d)
};
window.onload = calcfailback;
EN

回答 3

Code Review用户

回答已采纳

发布于 2012-08-07 01:35:16

我不太熟悉CSS,但我对JS相关部分有几点评论:

煅烧故障恢复

我把这叫做calcFailbackcalc_failback

1 var语句

每个作用域只有一个var语句,这是相当标准的做法。这是因为JS在本质上将所有变量声明拉到一个作用域的顶部。

代码语言:javascript
复制
function f() {
    var x = 5;
    if (x == 5) {
        var y = 10;
    }
}

实际上相当于:

代码语言:javascript
复制
function f() {
    var x = 5;
    var y;
    if (x == 5) {
        y = 10;
    }
}

由于这个原因(或者更重要的是,如果您忘记了它被默默地解释为这一点,可能会导致奇怪的bug),一个相当普遍的做法是,每个作用域只使用一个var声明:

代码语言:javascript
复制
function f() {
    var x = 5,
        y;
    ...
}

没有意义的非操作分支

代码语言:javascript
复制
if (newwidth == "10") {}

那是毫无意义的。在某些边界情况下,有一个空分支可能很有用,但是对于像这样的琐碎的分支,只需:

代码语言:javascript
复制
if (newwidth != "10") { ... }

变量命名

我会使用下划线或camelCase,这样就有了某种视觉上的词语分离。new_widthnewWidthnewwidth更容易阅读和理解。

调用其他函数的

函数通常是无意义的

代码语言:javascript
复制
var x = function () { f(); };

所有这些都是创建一个绑定到x的函数,当调用该函数时,调用f

除非您特别希望这样做以隐藏调用上下文,否则通常最好将其编写为:

代码语言:javascript
复制
var x = f;

在这种情况下,x()仍然调用f,它只是在没有间接层的情况下这样做。

不过,从技术上讲,这是不同的。没有上下文的函数默认为window对象作为上下文(或严格模式下的undefined )。

这意味着f中的this可能是不同的,这取决于x的调用方式。

例如:

代码语言:javascript
复制
function f() {
    console.log(this);
}
var x = function() { f(); },
    obj = {foo: "bar"};

x.call(obj); //The console.log will output either window or undefined depending on strict mode
//('this' inside of the wrapper function, however, would be obj)

与之相比:

代码语言:javascript
复制
function f() {
    console.log(this);
}
var x = f,
    obj = {foo: "bar"};

x.call(obj); //The console.log will output obj (in other words, 'this' inside of 'f' would be 'obj'

您的脚本破坏任何其他脚本

当您分配window.onloadwindow.onresize属性时,您可能需要编写旧的处理程序。

“但这是我页面上唯一的脚本!”你说。

这是目前唯一的剧本。

为了避免将来出现一些奇怪的错误,我可能会使用一个简单的函数来进行堆栈绑定:

代码语言:javascript
复制
function bindEvt(target, evt, func) {
    var prev = target[evt];
    if (typeof prev !== "function") {
        target[evt] = func;
    } else {
        target[evt] = function() {
            prev.apply(this, Array.prototype.slice.call(arguments));
            func.apply(this, Array.prototype.slice.call(arguments));
        };
    }
    return target[evt];
}

它的用途如下:

代码语言:javascript
复制
function f() { ... };
bindEvt(window, "onresize", f);

(注:这实际上应该被用作一个想法而不是一个实际的实现。我完全相信这个函数至少有一个主要问题。)

建议实现

我可能会写成这样:

代码语言:javascript
复制
// CSS calc() replacement
function calcFailback(){
    var d = document.createElement('div'),
        _body = document.getElementsByTagName('body')[0],
        newWidth;

    //functions are actually hoisted too, though in a silenty different way
    function resize() {
        document.getElementById('content').style.height = window.innerHeight - 40 + 'px';
        document.getElementById('content').style.width = window.innerWidth - 300 +'px';
        document.getElementById('sidebar').style.height = window.innerHeight - 40 + 'px';
    }; //You will not usuaully see a ; here.  There's nothing wrong with it though.

    _body.appendChild(d);

    d.style.visibility = 'hidden';
    d.style.width = "-webkit-calc(10px)";
    d.style.width = "-o-calc(10px)";  
    d.style.width = "-moz-calc(10px)"; 
    d.style.width = "calc(10px)";   

    newWidth = d.offsetWidth;

    if (newWidth != "10") { //I might use either !== "10" or !== 10 if you know the type

        resize();
        window.onresize = resize;

        //I might consider inlining the function defition since it's a simple function.
        //You could use a structure like:
        //window.onresize = function() { ... };
        //window.onresize();
        //This is not the same thing as a legitimate onresize event happening though, so you'd need to be
        //careful to make sure that your handler is capable of handling fake events like this.
        //A bit more 'authentic' way might be:
        //window.onresize.call(window); since the handler is probably (I'm not sure) called with window as the context
        //This would still neglect the parameters though.

    } //There was no reason for the ; here

    _body.removeChild(d); //This should have a ; here (mainly for styling purposes in this context, but it's a good habit for situations where it does matter)

}

编辑

关于它的价值,这里有一个使用类似bindEvt函数的(非常)简单的例子:小提琴

票数 2
EN

Code Review用户

发布于 2012-08-07 01:51:06

泛化您的代码可能是个好主意,这样您就可以以不同的值使用它。我并不是建议您支持完整的calc()语法,但是如果您计划在多个地方使用它,那么至少使其可配置是有用的。

不过,对于您所拥有的代码,我只是有几个建议:

  1. 我通常避免在变量名中使用下划线,但这只是一种偏好(尽管我已经看到了很多风格指南)。
  2. if (newwidth == "10"){} else替换为if (newwidth !== 10) {。与其在真实情况下什么都不做,不如切换比较,跳过其他操作。您还可以直接与数字10进行比较(使用严格相等运算符),而不是进行字符串比较。
  3. if语句中,ECMAScript中的函数声明在技术上是不合法的(它们只允许在全局范围内,或者在函数的顶层)。浏览器倾向于将其作为扩展来支持,但是它们的行为不同,并且可能导致问题,所以最好避免这种情况。函数表达式很好,所以我直接给window.onresize分配了一个匿名函数,并通过它调用了它。您还可以将函数赋值给一个变量(将function resize() {...}替换为var resize = function() {...};)。
  4. 与其三次调用document.getElementById('content'),不如将样式对象存储在变量中并引用它。你将获得一个速度和文件大小的优势。
  5. 函数声明后或if语句块之后不需要分号。

我的结局是:

代码语言:javascript
复制
// CSS calc() replacement
function calcfailback() {
    var d = document.createElement('div');

    // 1
    var body = document.getElementsByTagName('body')[0];
    body.appendChild(d);
    d.style.visibility = 'hidden';
    d.style.width = "-webkit-calc(10px)";
    d.style.width = "-o-calc(10px)";  
    d.style.width = "-moz-calc(10px)"; 
    d.style.width = "calc(10px)";   
    var newwidth = d.offsetWidth;

    // 2
    if (newwidth !== 10) {
        // 3
        window.onresize = function() {
            // 4
            var contentStyle = document.getElementById('content').style;
            contentStyle.height = window.innerHeight - 40 + 'px';
            contentStyle.width = window.innerWidth - 300 +'px';
            contentStyle.height = window.innerHeight - 40 + 'px';
        };
        window.onresize();
    } // 5
    body.removeChild(d);
} // 5
window.onload = calcfailback;
票数 3
EN

Code Review用户

发布于 2014-09-10 04:20:14

没有理由检查-o-前缀。Presto引擎下的Opera从来没有对calc()的支持,不管是前缀还是其他。闪烁引擎下的Opera支持它,没有前缀。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/14392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档