logo头像

总有人间一两风,填我十万八千梦

前端可以这样玩儿!

本文总结了一些前端冷知识,相信看完之后的你一定会觉得前端为什么如此好玩儿?!(源自 Quora 上的一个帖子,同时又查阅了一些其他资料)

HTML 篇

浏览器地址栏运行 JavaScript 代码

这个相信很多人是知道的,在浏览器地址栏可以直接运行 JavaScript 代码,做法是以 javascript: 开头后跟要执行的语句。比如:

1
javascript:alert('hello Merrier :)');

将以上代码贴到浏览器地址栏回车后 alert 正常执行,一个弹窗神现。需要注意的是如果是通过 copy paste 代码到浏览器地址栏的话,IE 及 Chrome 会自动去掉代码开头的 javascript:,所以需要手动添加起来才能正确执行,而 Firefox 中虽然不会自动去掉,但它根本就不支持在地址栏运行 JS 代码,sigh~

浏览器地址栏运行 HTML 代码

如果说上面那条小秘密知道的人还算多的话,这条秘笈知道的人就要少一些了,在非 IE 内核的浏览器地址栏可以直接运行 HTML 代码!比如在地址栏输入以下代码然后回车运行,会出现指定的页面内容。

1
data:text/html,<h1>Hello, world!</h1>

你造么,可以把浏览器当编辑器

还是浏览器地址栏上做文章,将以下代码贴到地址栏运行后浏览器变成了一个原始而简单的编辑器,与 Windows 自带的 notepad 一样,吼吼。

1
data:text/html, <html contenteditable>

归根结底多亏了 HTML5 中新加的 contenteditable 属性,当元素指定了该属性后,元素的内容成为可编辑状态。

整个页面变得可编辑

将以下代码放到 console 执行后,整个页面将变得可编辑,随意践踏吧~

1
document.body.contentEditable='true';

利用 a 标签自动解析 URL

很多时候我们有从一个 URL 中提取域名,查询关键字,变量参数值等的需要,而万万没想到可以让浏览器方便地帮我们完成这一任务而不用我们写正则去抓取。方法就在 JS 代码里先创建一个a标签然后将需要解析的 URL 赋值给 a 的 href 属性,然后就得到了一切我们想要的了。

1
2
3
var a = document.createElement('a');
a.href = 'http://www.cnblogs.com/wayou/p/';
console.log(a.host);

利用这一原理,稍微扩展一下,就得到了一个更加健壮的解析 URL 各部分的通用方法了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return {
source: url,
protocol: a.protocol.replace(':',''),
host: a.hostname,
port: a.port,
query: a.search,
params: (function(){
var ret = {},
seg = a.search.replace(/^\?/,'').split('&'),
len = seg.length, i = 0, s;
for (;i<len;i++) {
if (!seg[i]) { continue; }
s = seg[i].split('=');
ret[s[0]] = s[1];
}
return ret;
})(),
file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
hash: a.hash.replace('#',''),
path: a.pathname.replace(/^([^\/])/,'/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
segments: a.pathname.replace(/^\//,'').split('/')
};
}

页面拥有 ID 的元素会创建全局变量

在一张 HTML 页面中,所有设置了 ID 属性的元素会在 JavaScript 的执行环境中创建对应的全局变量,这意味着 document.getElementById 像人的阑尾一样显得多余了。但实际项目中最好老老实实该怎么写就怎么写,毕竟常规代码出乱子的机会要小得多。

1
2
3
4
<div id="sample"></div>
<script type="text/javascript">
console.log(sample);
</script>

加载 CDN 文件时,可以省掉 HTTP 标识

现在很流行的 CDN 即从专门的服务器加载一些通用的 JS 和 CSS 文件,出于安全考虑有的 CDN 服务器使用 HTTPS 方式连接,而有的是传统的 HTTP,其实我们在使用时可以忽略掉这个,将它从 URL 中省去。

1
<script src="//domain.com/path/to/script.js"></script>

利用 script 标签保存任意信息

将 script 标签设置为 type=’text’ 然后可以在里面保存任意信息,之后可以在 JavaScript 代码中很方便地获取。

1
2
3
<script type="text" id="template">
<h1>This won't display</h1>
</script>
1
var text = document.getElementById('template').innerHTML

CSS 篇

我的鼠标呢?

相信你看完以下代码后能够预料到会出现什么效果。

1
2
3
*{
cursor: none!important;
}

简单的文字模糊效果

以下两行简单的 CSS3 代码可达到将文字模糊化处理的目的,出来的效果有点像使用 PS 的滤镜,so cool!

1
2
3
4
p {
color: transparent;
text-shadow: #111 0 0 5px;
}

垂直居中

当然你可以将容器设置为 display: table,然后将子元素也就是要垂直居中显示的元素设置为 display: table-cell,然后加上 vertical-align: middle 来实现,但此种实现往往会因为 display: table 而破坏整体布局,那还不如直接用 table 标签了呢。下面这个样式利用了 translate 来巧妙实现了垂直居中样式,需 IE9+。

1
2
3
4
5
.center-vertical {
position: relative;
top: 50%;
transform: translateY(-50%);
}

相比而言,水平居中要简单得多,像上面提到的 text-align: center,经常用到的技巧还有 margin: 0 auto。但对于 margin 大法也只在子元素宽度小于容器宽度时管用,当子元素宽度大于容器宽度时此法失效。如法炮制,利用 left 和 transform 同样可实现水平居中,不过意义不大,毕竟 text-align 和 margin 差不多满足需求了。

1
2
3
4
5
.center-horizontal {
position: relative;
left: 50%;
transform: translateX(-50%);
}

多重边框

利用重复指定 box-shadow 来达到多个边框的效果

1
2
3
4
5
6
7
8
9
10
/* CSS Border with Box-Shadow Example */
div {
box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2),
0 0 0 12px rgba(0, 0, 0, 0.2),
0 0 0 18px rgba(0, 0, 0, 0.2),
0 0 0 24px rgba(0, 0, 0, 0.2);
height: 200px;
margin: 50px auto;
width: 400px
}

实时编辑 CSS

通过设置 style 标签的 display: block 样式可以让页面的 style 标签显示出来,并且加上 contentEditable 属性后可以让样式成为可编辑状态,更改后的样式效果也是实时更新呈现的。此技巧在 IE 下无效。拥有此技能者,逆天也!

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<body>
<style style="display:block" contentEditable>
body { color: blue }
</style>
</body>
</html>

创建长宽比固定的元素

通过设置父级窗口的 padding-bottom 可以达到让容器保持一定的长度比的目的,这在响应式页面设计中比较有用,能够保持元素不变形。

1
2
3
4
5
<div style="width: 100%; position: relative; padding-bottom: 20%;">
<div style="position: absolute; left: 0; top: 0; right: 0; bottom: 0;background-color:yellow;">
this content will have a constant aspect ratio that varies based on the width.
</div>
</div>

CSS 中也可以做简单运算

通过 CSS 中的 calc 方法可以进行一些简单的运算,从而达到动态指定元素样式的目的。

1
2
3
.container{
background-position: calc(100% - 50px) calc(100% - 20px);
}

JavaScript 篇

生成随机字符串

利用 Math.random 和 toString 生成随机字符串,来自前一阵子看到的一篇博文。这里的技巧是利用了 toString 方法可以接收一个基数作为参数的原理,这个基数从 2 到 36 封顶。如果不指定,默认基数是 10 进制。略屌!

1
2
3
4
5
6
7
function generateRandomAlphaNum(len) {
var rdmString = "";
for (; rdmString.length < len; ){
rdmString += Math.random().toString(36).substr(2);
}
return rdmString.substr(0, len);
}

整数的操作

JavaScript 中是没有整型概念的,但利用好位操作符可以轻松处理,同时获得效率上的提升。|0 和 ~~ 是很好的一个例子,使用这两者可以将浮点转成整型且效率方面要比同类的 parseInt, Math.round 要快。在处理像素及动画位移等效果的时候会很有用。性能比较见此

1
2
var foo = (12.4 / 4.13) | 0; // 结果为3
var bar = ~~(12.4 / 4.13); // 结果为3

重写原生浏览器方法以实现新功能

下面的代码通过重写浏览器的 alert 让它可以记录弹窗的次数。

1
2
3
4
5
6
7
8
9
(function() {
var oldAlert = window.alert,
count = 0;
window.alert = function(a) {
count ++;
oldAlert(a + "\n You've called alert " + count + " times now. Stop, it's evil!");
};
})();
alert("Hello World");

console 显示图片以及为文字加样式

在 Chrome 的开发者工具里,console 可以加样式,可以显示缤纷的颜色,甚至图片。简直爽翻了。具体来说,是可以对输出到 console 控制台的文字进行 CSS 控制。格式如下:

1
console.log("%c需要输出的信息 ", "css 代码");

下面是一些已经写好的 console 新玩法代码,可以在 chrome 控制台里面实测(关于 console 的更多玩法,推荐 MDN关于console的文档):

1. 3D Text

1
2
3
console.log("%c3D Text"," text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,
0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),
0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:5em")

2. Colorful CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log("%cColorful CSS","background: rgba(252,234,187,1);background: -moz-linear-gradient(left, rgba(252,234,187,1) 0%, 
rgba(175,250,77,1) 12%, rgba(0,247,49,1) 28%, rgba(0,210,247,1) 39%,rgba(0,189,247,1) 51%, rgba(133,108,217,1) 64%,
rgba(177,0,247,1) 78%, rgba(247,0,189,1) 87%, rgba(245,22,52,1) 100%);background: -webkit-gradient(left top, right top,
color-stop(0%, rgba(252,234,187,1)), color-stop(12%, rgba(175,250,77,1)), color-stop(28%, rgba(0,247,49,1)),
color-stop(39%, rgba(0,210,247,1)), color-stop(51%, rgba(0,189,247,1)), color-stop(64%, rgba(133,108,217,1)),
color-stop(78%, rgba(177,0,247,1)), color-stop(87%, rgba(247,0,189,1)), color-stop(100%, rgba(245,22,52,1)));
background: -webkit-linear-gradient(left, rgba(252,234,187,1) 0%, rgba(175,250,77,1) 12%, rgba(0,247,49,1) 28%,
rgba(0,210,247,1) 39%, rgba(0,189,247,1) 51%, rgba(133,108,217,1) 64%, rgba(177,0,247,1) 78%, rgba(247,0,189,1) 87%,
rgba(245,22,52,1) 100%);background: -o-linear-gradient(left, rgba(252,234,187,1) 0%, rgba(175,250,77,1) 12%, rgba(0,247,49,1) 28%,
rgba(0,210,247,1) 39%, rgba(0,189,247,1) 51%, rgba(133,108,217,1) 64%, rgba(177,0,247,1) 78%, rgba(247,0,189,1) 87%,
rgba(245,22,52,1) 100%);background: -ms-linear-gradient(left, rgba(252,234,187,1) 0%, rgba(175,250,77,1) 12%, rgba(0,247,49,1) 28%,
rgba(0,210,247,1) 39%, rgba(0,189,247,1) 51%, rgba(133,108,217,1) 64%, rgba(177,0,247,1) 78%, rgba(247,0,189,1) 87%,
rgba(245,22,52,1) 100%);background: linear-gradient(to right, rgba(252,234,187,1) 0%, rgba(175,250,77,1) 12%, rgba(0,247,49,1) 28%,
rgba(0,210,247,1) 39%, rgba(0,189,247,1) 51%, rgba(133,108,217,1) 64%, rgba(177,0,247,1) 78%, rgba(247,0,189,1) 87%, rgba(245,22,52,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fceabb', endColorstr='#f51634', GradientType=1 );font-size:5em")

3. Rainbow Text

1
2
3
console.log('%cRainbow Text ', 'background-image:-webkit-gradient( linear, left top, right top, color-stop(0, #f22), 
color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2),
color-stop(0.9, #ff2), color-stop(1, #f22) );color:transparent;-webkit-background-clip: text;font-size:5em;');

4. 输出图片

1
console.log("%c", "padding:50px 300px;line-height:120px;background:url('https://ss0.bdstatic.com/5aV1bjqh\_Q23odCf/static/superman/img/logo/bd\_logo1_31bdc765.png') no-repeat;");

不声明第三个变量的值交换

我们都知道交换两个变量值的常规做法,那就是声明一个中间变量来暂存。但鲜有人去挑战不声明中间变量的情况,下面的代码给出了这种实现。蛮有创意的。

1
2
var a = 1, b = 2;
a= [b, b = a][0];

万物皆对象

在 JavaScript 的世界,万物皆对象。除了 null 和 undefined,其他基本类型数字,字符串和布尔值都有对应有包装对象。对象的一个特征是你可以在它身上直接调用方法。对于数字基本类型,当试图在其身上调用 toString 方法会失败,但用括号括起来后再调用就不会失败了,内部实现是用相应的包装对象将基本类型转为对象。所以 (1).toString() 相当于 new Number(1).toString()。因此,你的确可以把基本类型数字,字符串,布尔等当对象使用的,只是注意语法要得体。同时我们注意到,JavaScript 中数字是不分浮点和整形的,所有数字其实均是浮点类型,只是把小数点省略了而已,比如你看到的 1 可以写成 1.,这也就是为什么当你试图 1.toString() 时会报错,所以正确的写法应该是这样:1..toString(),或者如上面所述加上括号,这里括号的作用是纠正 JS 解析器,不要把 1 后面的点当成小数点。内部实现如上面所述,是将 1. 用包装对象转成对象再调用方法。

If 语句的变形

当你需要写一个 if 语句的时候,不妨尝试另一种更简便的方法,用 JavaScript 中的逻辑操作符来代替。

1
2
3
4
5
6
7
var day = (new Date).getDay() === 0;
//传统if语句
if (day) {
alert('Today is Sunday!');
};
//运用逻辑与代替if
day && alert('Today is Sunday!');

比如上面的代码,首先得到今天的日期,如果是星期天,则弹窗,否则什么也不做。我们知道逻辑操作存在短路的情况,对于逻辑与表达式,只有两者都真才结果才为真,如果前面的 day 变量被判断为假了,那么对于整个与表达式来说结果就是假,所以就不会继续去执行后面的 alert 了,如果前面 day 为真,则还要继续执行后面的代码来确定整个表达式的真假。利用这点达到了 if 的效果。

禁止别人以 iframe 加载你的页面

下面的代码已经不言自明了,没什么好多说的。

1
2
3
if (window.location != window.parent.location) {
window.parent.location = window.location;
}

参考文章

支付宝打赏 微信打赏

听说赞过就能年薪百万