Yoko Kuok's Blog


  • 首页

  • 关于

  • 归档

  • 标签

Javascript Traps

发表于 2017-04-12

javascript 陷阱集

考作用域

1
2
3
4
5
6
7
(function() {
var b = 5;
var a = b;
b = 6;
console.log(a,b);
//5 6
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var g = 0;
function f() {
    // 这里面就形成了一个方法作用域, 能够保护其中的变量不能被外部访问
    // 方法作用域能够访问全局作用域
    var a = 1;
    console.log(g);
    // 嵌套方法作用域
    function ff() {
        // 这里面再度形成了一个方法作用域
        // 其中可以访问外部的那个方法作用域
        var aa = 2;
        console.log(a);
    }
    // 出了 ff 的作用域就不能访问其中的东西了
    // console.log(aa); // 报错 ReferenceError: aa is not defined
}
f();
// console.log(a); // 报错 ReferenceError: a is not defined

考声明提前

1
2
3
4
5
6
7
8
9
10
11
//考声明提前
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();

考 this

1
2
3
4
5
6
7
8
9
10
11
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
getFullname: function() {
return this.fullname;
}
};
console.log(obj.getFullname()); //Colin Ihrig
var test = obj.getFullname; //John Doe
console.log(test());

制造干扰因素的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
},
getFullname: function() {
return this.fullname;
}
};
console.log(obj.prop.getFullname()); //Aurelio De Rosa
console.log(obj.getFullname()); //Colin Ihrig
var test = obj.prop.getFullname; //John Doe
console.log(test());

分号陷阱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//分号陷阱
function fn(){
return {
x:1
};
} //{x:1}
function fn(){
return
{
x:1
};
}
console.log(fn()) //undefined

小数相加

1
2
3
4
//不要相信js的符点运算结果,但是整数是可依赖的
0.1 + 0.2 不等于 0.3 //0.30000000000000004
可用如下
(0.1*10 + 0.2*10)/10

HTML5 Tricks

发表于 2017-04-06

线条

线条样式
  • lineCap 设置或返回线条末端线帽的样式。
  • lineJoin 当两条线交汇时,设置或返回所创建边角的类型


1
2
//向线条的每个末端添加平直/圆形、正方形的边缘
context.lineCap="butt|round|square";

lineJoin 线条交叉


1
2
//斜角、圆角、尖角
context.lineJoin="bevel|round|miter";

Canvas宽高

canvas里的宽高和css里的宽高

删除canvas里的宽高,宽:400;高:300;写在style里的效果:

  • 为什么两者的效果会不一样呢?
      canvas跟其他标签一样,也可以通过css来定义样式。但这里需要注意的是:canvas的默认宽高为300px 150px,在css中为canvas定义宽高,实际上把宽高为300px 150px的画布进行了拉伸,如果在这样的情况下进行canvas绘图,你得到的图形可能就是变形的效果。所以,在canvas绘图时,应该在canvas标签里直接定义宽高。

canvas宽高设置

  • 分别用两种方式设置canvas的高度
    1
    2
    3
    $("#myCanvas").attr({
    "height": 300
    });
1
2
3
4
5
6
console.log("canvas高度", $("#myCanvas").attr("height"), $("#myCanvas").attr("width"));
$("#myCanvas").attr({
"height": 300
});
var height = $("#myCanvas").height(200);
console.log("canvas高度", height, $("#myCanvas").attr("height"), $("#myCanvas").attr("width"));
1
<canvas id="myCanvas" width="800" height="300" style="background: url(&quot;./images/keji.jpg&quot;) 0px 0px no-repeat; display: block; height: 200px;">你的浏览器居然不支持Canvas?!赶快换一个吧!!</canvas>

CSS

发表于 2017-03-31

CSS 常见问题(以下内容包含LESS语法)

span 标签插入图片

background需要加入 display: inline-block;

  • 否则图片无法显示出来
  • PS: less语法
1
2
3
4
5
6
7
8
9
10
11
homework-height:42px;
homework-width:58px;
homework-position-horizontal: -58px;
homework-position-vertical: -42px;
homework-icon: url(../images/student/icons.png);
.homework-chinese{
display: inline-block; //important
height: @homework-height;
width: @homework-width;
background: @homework-icon no-repeat @homework-position-horizontal*0 @homework-position-vertical*0;
}

分栏布局

需要加入 box-sizing: border-box;

  • 否则导致div被挤到下一行
1
2
3
4
5
6
7
.content-col-6 {
width: 50%;
padding: @content-col-padding;
position: relative;
float: left;
box-sizing: border-box;
}

2个 img中间 出现空格

需要添加 font-size: 0px;

  • 否则中间的空隙无法去除
1
2
3
4
<div style=" display:inline; font-size: 0px;">
<img src="../static/images/student/logo_1.png">
<img style="vertical-align: top;" src="../static/images/student/logo_2.png">
</div>

遮罩

需要添加 透明度

0.9; ```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
```javascript
#mask {
bottom: 0;
left: 0;
opacity: 0.9; /* important*/
position: fixed;
right: 0;
top: 0;
background: grey;
filter:alpha(opacity=50); /*IE6*/
-moz-opacity:0.5; /*Mozilla old version*/
-khtml-opacity: 0.5; /*Safari old version*/
}

要获取div的display值

需要在div里添加

none;"```
1
2
3
4
5
6
7
8
9
10
11
12
13
- 不能在css里写,js无法读取
```javascript
<div class="mask" style="display: none;" onclick="showMask(3);">
</div>
function showMask(n) {
var mask = document.getElementsByClassName("mask");
if(mask[n].style.display =='none'){
mask[n].style.display = 'block';
}else{
mask[n].style.display = 'none';
}
}

background

image 居中

1
background:url(logo.png) center center no-repeat;

image 全屏

1
background-size:100% 100%;

image 拉伸

  • 顺序不能翻转
1
2
background:url('../../static/images/login/bg0.png') no-repeat 0 0 / 100% 100% rgba(0, 0, 0, 0);
background-size:100% 100%;

image底下有白边

首先 img 元素默认对齐方式为 vertical-align: baseline;,这就导致了,baseline 以下的部分被空了出来,显示了背景的白色。

问题找到了,对症下药可得出下面的解决方案:

  • 根本上消除 img 的对齐方式 —— 块状化:
1
2
3
img {
display: block;
}
  • 更改 img 对齐方式,以下三种均可
1
2
3
4
5
img {
vertical-align: top;
vertical-align: middle;
vertical-align: bottom;
}
  • 更改行高,行高是两条 baseline 之间的距离,因此可以暴力的让行高消失
1
2
3
4
{
line-height: 0;
/* font-size: 0; 当 line-height 使用数值、百分比或者 rem 定义时也可用这种方式,因为 line-height 参照的是 font-size 的值*/
}

input 点击有蓝边

1
2
3
input,textarea{
outline:none;
}

CSS Tricks

居中

水平居中

1
2
display: flex;
justify-content: center; /* 水平居中 */

垂直居中

1
2
display: flex;
align-items: center;

绝对居中

1
2
3
4
5
6
7
8
9
10
11
div {
width: 300px;
height: 300px;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
background-color: pink; /* 方便看效果 */
}
  • 利用 flex 布局
    • 实际使用时应考虑兼容性
1
2
3
4
5
6
7
8
9
10
11
.container {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.container div {
width: 100px;
height: 100px;
background-color: pink; /* 方便看效果 */
}
  • 未知容器的宽高,利用 transform 属性
1
2
3
4
5
6
7
8
9
10
div {
width:500px;
height:300px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute; /* 相对定位或绝对定位均可 */
background-color: pink; /* 方便看效果 */
}

动画&特效

旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.profile-circle-img {
width: 130px;
height: 130px;
border-radius: 50%;
left: 65px;
top: 35px;
transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
}
.profile-circle-img:hover {
transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
}

三角形

  • 参考网址:http://www.feelcss.com/three-pure-css-to-achieve-the-triangle-method.html
利用 border 属性实现三角形
1
2
3
4
5
6
7
.arrow-up {
width: 0;
height: 0;
border-left:20px solid transparent;
border-right:20px solid transparent;
border-bottom:20px solid black;
}
1
2
3
4
5
6
7
#demo {
width: 0;
height: 0;
border-width: 20px;
border-style: solid;
border-color: transparent transparent red transparent;
}
利用 CSS3 transfrom 旋转 45 度实现三角形

  • HTML
1
2
3
4
<div class="message-box">
<span>我是利用 css transfrom 属性字符实现的</span>
<div class="triangle-css3 transform ie-transform-filter"></div>
</div>
  • CSS
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
.message-box {
position:relative;
width:240px;
height:60px;
line-height:60px;
background:#E9FBE4;
box-shadow:1px 2px 3px #E9FBE4;
border:1px solid #C9E9C0;
border-radius:4px;
text-align:center;
color:#0C7823;
}
.triangle-css3 {
position:absolute;
bottom:-8px;
bottom:-6px;
left:30px;
overflow:hidden;
width:13px;
height:13px;
background:#E9FBE4;
border-bottom:1px solid #C9E9C0;
border-right:1px solid #C9E9C0;
}
.transform {
-webkit-transform:rotate(45deg);
-moz-transform:rotate(45deg);
-o-transform:rotate(45deg);
transform:rotate(45deg);
}
/*ie7-9*/
.ie-transform-filter {
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(
M11=0.7071067811865475,
M12=-0.7071067811865477,
M21=0.7071067811865477,
M22=0.7071067811865475,
SizingMethod='auto expand')";
filter: progid:DXImageTransform.Microsoft.Matrix(
M11=0.7071067811865475,
M12=-0.7071067811865477,
M21=0.7071067811865477,
M22=0.7071067811865475,
SizingMethod='auto expand');
}

鼠标、光标

手指

1
cursor:pointer;

文本

可编辑文本

1
<p contenteditable="true">这是一段可编辑的段落。请试着编辑该文本。</p>

文字超长省略

1
2
3
4
5
6
{
max-width:150px;
white-space:nowrap; /*强制文本在一行内显示*/
text-overflow:ellipsis; /*文字超出省略*/
overflow:hidden;
}

选择器 Selectors

1
<p class="key" id="principal">

class

1
2
3
.key {
color: green;
}

id

1
2
3
#principal {
font-weight: bolder;
}

伪类选择器(Pseudo-classes selectors)

伪类列表

  • https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Getting_Started/Selectors
1
2
3
4
5
body { background-color: #ffffc9 }
a:link { color: blue } /* 未访问链接 */
a:visited { color: purple } /* 已访问链接 */
a:hover { font-weight: bold } /* 用户鼠标悬停 */
a:active { color: lime } /* 激活链接 */

jQuery

发表于 2016-12-25

jQuery

jQuery基础

效果

隐藏、显示、切换,滑动,淡入淡出,以及动画

  • slow,fast,normal或毫秒

隐藏、显示、切换

  • hide()
  • show()
  • toggle()
1
2
3
$("#hide").click(function(){
$("p").hide(3000); //渐渐消失,slow,fast,normal或毫秒
});

淡入淡出

  • fadeIn()
  • fadeOut()
  • fadeToggle()
  • fadeTo() , 渐变为给定的不透明度(值介于 0 与 1 之间)
1
2
3
4
5
$("button").click(function(){
$("#div1").fadeIn();
$("#div2").fadeIn("slow");
$("#div3").fadeIn(3000);
});
1
2
3
4
5
$("button").click(function(){
$("#div1").fadeTo("slow",0.15);
$("#div2").fadeTo("slow",0.4);
$("#div3").fadeTo("slow",0.7);
});

滑动

  • slideDown()
  • slideUp()
  • slideToggle()
1
2
3
$("#flip").click(function(){
$("#panel").slideDown();
});

动画

提示:

  • 默认地,所有 HTML 元素都有一个静态位置,且无法移动。
    如需对位置进行操作,要记得首先把元素的 CSS position 属性设置为 relative、fixed 或 absolute!
  • 可以用 animate() 方法来操作所有 CSS 属性吗?
    是的,几乎可以!不过,需要记住一件重要的事情:当使用 animate() 时,必须使用 Camel 标记法书写所有的属性名,比如,必须使用 paddingLeft 而不是 padding-left,使用 marginRight 而不是 margin-right,等等。
1
2
3
4
5
6
7
$("button").click(function(){
$("div").animate({
left:'50px',
height:'+=10px',
width:'+=10px'
});
});

使用队列功能

1
2
3
4
5
6
7
$("button").click(function(){
var div=$("div");
div.animate({height:'300px',opacity:'0.4'},"slow");
div.animate({width:'300px',opacity:'0.8'},"slow");
div.animate({height:'100px',opacity:'0.4'},"slow");
div.animate({width:'100px',opacity:'0.8'},"slow");
});

停止动画

  • stop()
1
2
3
$("#stop").click(function(){
$("#panel").stop();
});

Callback

  • 防止动画之后的语句可能会产生错误或页面冲突
1
2
3
$("p").hide(1000,function(){
alert("The paragraph is now hidden");
});

错误示范:

1
2
$("p").hide(1000);
alert("The paragraph is now hidden");

Chaining

1
2
3
$("#p1").css("color","red")
.slideUp(2000)
.slideDown(2000);

HTML

获取内容&设置

  • text() - 设置或返回所选元素的文本内容
  • html() - 设置或返回所选元素的内容(包括 HTML 标记)
  • val() - 设置或返回表单字段的值
  • attr() - 设置/改变属性值
1
2
3
$("#btn1").click(function(){
alert("Text: " + $("#test").text());
});
1
2
3
4
5
6
$("button").click(function(){
$("#w3s").attr({
"href" : "http://www.w3school.com.cn/jquery",
"title" : "W3School jQuery Tutorial"
});
});

添加元素

  • append() - 在被选元素的结尾插入内容
  • prepend() - 在被选元素的开头插入内容
  • after() - 在被选元素之后插入内容
  • before() - 在被选元素之前插入内容
1
2
3
4
5
6
7
$("#btn1").click(function(){
$("p").append(" <b>Appended text</b>.");
});
$("#btn2").click(function(){
$("ol").append("<li>Appended item</li>");
});

删除元素

  • remove() - 删除被选元素(及其子元素)
    • jQuery remove() 方法也可接受一个参数,允许您对被删元素进行过滤。
  • empty() - 从被选元素中删除子元素
1
$("p").remove(".italic");

CSS类

  • addClass() - 向被选元素添加一个或多个类
  • removeClass() - 从被选元素删除一个或多个类
  • toggleClass() - 对被选元素进行添加/删除类的切换操作
  • css() - 设置或返回样式属性
1
2
3
4
$("button").click(function(){
$("h1,h2,p").addClass("blue");
$("div").addClass("important");
});
1
2
3
$("button").click(function(){
$("#div1").addClass("important blue");
});

css()

设置或返回被选元素的一个或多个样式属性。

  • 返回首个匹配元素的 background-color 值
1
$("p").css("background-color");
  • 为所有匹配元素设置 background-color 值
1
$("p").css("background-color","yellow");
  • 设置多个 CSS 属性
1
2
3
4
$("p").css({
"background-color":"yellow",
"font-size":"200%"
});

尺寸

  • width()
    • 设置或返回元素的宽度(不包括内边距、边框或外边距)
  • height()
    • 设置或返回元素的高度(不包括内边距、边框或外边距)
  • innerWidth()
    • 返回元素的宽度(包括内边距)
  • innerHeight()
    • 返回元素的高度(包括内边距)
  • outerWidth()
    • 返回元素的宽度(包括内边距和边框)
  • outerHeight()
    • 返回元素的宽度(包括内边距和边框)
1
2
3
4
5
6
$("button").click(function(){
var txt="";
txt+="Width: " + $("#div1").width() + "</br>";
txt+="Height: " + $("#div1").height();
$("#div1").html(txt);
});

遍历

祖先

  • parent()
  • parents()
  • parentsUntil()
1
2
3
$(document).ready(function(){
$("span").parent();
});

后代

  • children()
  • find()
    • 返回被选元素的后代元素,一路向下直到最后一个后代。
1
2
3
4
5
6
$(document).ready(function(){
$("div")
.children("p.1") // <p> class="1"
.css({"color":"red",
"border":"2px solid red"});
});
1
2
3
$(document).ready(function(){
$("div").find("*");
});

同胞

  • siblings()
  • next()
  • nextAll()
  • nextUntil()
  • prev()
  • prevAll()
  • prevUntil()
1
2
3
$(document).ready(function(){
$("h2").siblings();
});

过滤

  • first()
  • last()
  • eq()
    • 返回被选元素中带有指定索引号的元素。ps: 从0开始
1
2
3
$(document).ready(function(){
$("div p").first();
});
  • filter()
  • not()
    • 返回不匹配标准的所有元素
1
2
3
$(document).ready(function(){
$("p").filter(".intro");
});

AJAX

加载

  • load()
1
2
3
4
5
$(document).ready(function(){
$("#btn1").click(function(){
$('#test').load('/example/jquery/demo_test.txt');
})
})

可以把 jQuery 选择器添加到 URL 参数

1
2
3
4
5
$(document).ready(function(){
$("button").click(function(){
$("#div1").load("/example/jquery/demo_test.txt #p1");
});
});
  • 可选的 callback 参数规定当 load() 方法完成后所要允许的回调函数
    • responseTxt - 包含调用成功时的结果内容
    • statusTXT - 包含调用的状态
    • xhr - 包含 XMLHttpRequest 对象
1
2
3
4
5
6
7
8
$("button").click(function(){
$("#div1").load("demo_test.txt",function(responseTxt,statusTxt,xhr){
if(statusTxt=="success")
alert("外部内容加载成功!");
if(statusTxt=="error")
alert("Error: "+xhr.status+": "+xhr.statusText);
});
});

Get/Post

  • GET - 从指定的资源请求数据
    • GET 方法可能返回缓存数据
  • POST - 向指定的资源提交要处理的数据

    • POST 也可用于从服务器获取数据。不过,POST 方法不会缓存数据,并且常用于连同请求一起发送数据
  • $.get()

  • $.post()
1
2
3
4
5
$("button").click(function(){
$.get("demo_test.asp",function(data,status){
alert("Data: " + data + "\nStatus: " + status);
});
});
1
2
3
<%
response.write("This is some text from an external ASP file.")
%>

使用 $.post() 连同请求一起发送数据

1
2
3
4
5
6
7
8
9
10
$("button").click(function(){
$.post("demo_test_post.asp",
{
name:"Donald Duck",
city:"Duckburg"
},
function(data,status){
alert("Data: " + data + "\nStatus: " + status);
});
});

这个 ASP 文件 (“demo_test_post.asp”) 类似这样:

1
2
3
4
5
6
7
<%
dim fname,city
fname=Request.Form("name")
city=Request.Form("city")
Response.Write("Dear " & fname & ". ")
Response.Write("Hope you live well in " & city & ".")
%>

杂项

jQuery 和其他 JavaScript 框架

  • noConflict()

通过全名替代简写的方式来使用 jQuery

1
2
3
4
5
6
$.noConflict();
jQuery(document).ready(function(){
jQuery("button").click(function(){
jQuery("p").text("jQuery 仍在运行!");
});
});

noConflict() 可返回对 jQuery 的引用,您可以把它存入变量

1
2
3
4
5
6
var jq = $.noConflict();
jq(document).ready(function(){
jq("button").click(function(){
jq("p").text("jQuery 仍在运行!");
});
});

把 $ 符号作为变量传递给 ready 方法。这样就可以在函数内使用 $ 符号了 - 而在函数外,依旧不得不使用 “jQuery”

1
2
3
4
5
6
$.noConflict();
jQuery(document).ready(function($){
$("button").click(function(){
$("p").text("jQuery 仍在运行!");
});
});


jQuery技巧

延时

  • 所有指令统一写在setTimeout里,不是setTimeout后面
  • hide函数里必须放一个0,不然延时不起作用
    1
    2
    3
    4
    5
    6
    7
    ```javascript
    $(function() {
    setTimeout(function() {
    $("divid").show();
    }, 6000);
    }) >
1
2
3
4
5
/**
* 1.delay函数是jquery 1.4.2新增的函数
* 2.hide函数里必须放一个0,不然延时不起作用
*/
$('#divid').delay(6000).hide(0);

自定义方法

toggleText

1
2
3
4
5
6
7
8
9
10
11
jQuery.fn.toggleText = function (value1, value2) {
return this.each(function () {
var $this = $(this),
text = $this.text();
if (text.indexOf(value1) > -1)
$this.text(text.replace(value1, value2));
else
$this.text(text.replace(value2, value1));
});
};

判断data-name

  • 判断 data-name 是否等于honour
1
2
3
4
5
6
<div class="content-box growup fl honour" data-name="honour">
</div>
if ( $(this).data('name') === 'honour' ){
$(document).find(".li-score").hide();
}

实时监听input变化

1
2
3
$("#brush-size").bind("input propertychange",function(){
ctx.lineWidth = $(this).val();
});

jQuery常错

获取input的值

  • var result1 = $(“#input_text1”).val();
  • var result2 = $(“input[id=’input_text2’]”).val();
  • var result3 = $(“input[id=’input_text3’]”).attr(“value”);
  • var result4 = $(“input[type=’text’]”).val();
  • var result5 = $(“input[name=’text’]”).val();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 获取文本框的值:方式一 -->
<div id="test1">
<input id="input_text1" type="text" value="test1" style="width: 100px;" />
<button id="button_text1">test1</button>
</div>
<!-- 获取文本框的值:方式二 -->
<div id="test2">
<input id="input_text2" type="text" value="test2" style="width: 100px;" />
<button id="button_text2">test2</button>
</div>
<!-- 获取文本框的值:方式三 -->
<div id="test3">
<input id="input_text3" type="text" value="test3" style="width: 100px;" />
<button id="button_text3">test3</button>
</div>
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
28
29
30
31
32
//使用id的方式获取
$(document).ready(function(){
//1
$("#button_text1").click(function(){
var result1 = $("#input_text1").val();
alert("result1 = " + result1);
});
//2
$("#button_text2").click(function(){
var result2 = $("input[id='input_text2']").val();
alert("result2 = " + result2);
});
//3
$("#button_text3").click(function(){
var result3 = $("input[id='input_text3']").attr("value");
alert("result3 = " + result3);
});
//4. 可以通过type的值来获取input中的值(未演示)
/*
$("#button_text4").click(function(){
var result4 = $("input[type='text']").val();
alert("result4 = " + result4);
});
*/
//5. 可以通过name的值来获取input中的值(未演示)
/*
$("#button_text5").click(function(){
var result5 = $("input[name='text']").val();
alert("result5 = " + result5);
});
*/
});

Git

发表于 2016-10-31

Git

常用操作

Git 基本操作

基本流程

  • git pull 拉下来
  • git status 查看状态
  • git add ./ 添加当前所有文件
  • git commit -m “Words you want to commit” 评论
  • git push origin master 发送

缓存

  • git stash
  • git stash list
  • git stash pop filename{munber}

分支

  • git checkout -b test 更换为分支

合并

  • git log
  • git merge (master)

Javascript

发表于 2016-10-08

Javascript

核心(ECMAScript)

Javascript

预留关键字 Reserved keywords

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords


控制结构

条件表达式的三元操作符
1
var allowed = (age > 18) ? "yes" : "no";
switch 语句
  • switch
  • case
  • break
  • defult
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    switch(action) {
    case 'draw':
    drawIt();
    break;
    case 'eat':
    eatIt();
    break;
    default:
    doNothing();
    }

对象

创建一个空对象
1
var obj = new Object();

对象字面量(object literal), JSON 格式的核心语法(优先选择)

1
var obj = {};

  • 在对象实例中定义一个对象:
    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {
    name: "Carrot",
    "for": "Max",
    details: {
    color: "orange",
    size: 12
    }
    }

对象的属性可以通过链式(chain)表示方法进行访问:

1
2
obj.details.color; // orange
obj["details"]["size"]; // 12


数组

特殊的属性——length(长度)属性

  • 这个属性的值通常比数组最大索引大 1。
  • 数组的长度是比数组最大索引值多一的数。

相关用法:

  • forEach();
  • push();

创建数组的传统方法

1
2
3
4
5
var a = new Array();
a[0] = "dog";
a[1] = "cat";
a[2] = "hen";
a.length; // 3

数组字面量(array literal)法(优先选择)

1
2
var a = ["dog", "cat", "hen"];
a.length; // 3

数组的长度是比数组最大索引值多一的数

1
2
3
var a = ["dog", "cat", "hen"];
a[100] = "fox";
a.length; // 101

访问不存在的数组,返回undefined

1
typeof(a[90]); // undefined

遍历数组 forEach():

1
2
3
["dog", "cat", "hen"].forEach(function(currentValue, index, array) {
// Do something with currentValue or array[index]
});

如果想在数组后追加元素,只需要:

1
a.push(item);


函数

1
2
3
4
5
6
7
8
9
function add() {
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++) {
sum += arguments[i];
}
return sum;
}
add(2, 3, 4, 5); // 14
  • 函数实际上是访问了函数体中一个名为 arguments 的内部对象,这个对象就如同一个类似于数组的对象一样,包括了所有被传入的参数。

自定义对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function makePerson(first, last) {
return {
first: first,
last: last,
fullName: function() {
return this.first + ' ' + this.last;
},
fullNameReversed: function() {
return this.last + ', ' + this.first;
}
}
}
s = makePerson("Simon", "Willison");
s.fullName(); // Simon Willison
s.fullNameReversed(); // Willison, Simon
  • 关键字 this:当使用在函数中时,this 指代当前的对象,也就是调用了函数的对象。如果在一个对象上使用点或者方括号来访问属性或方法,这个对象就成了 this。如果并没有使用“点”运算符调用某个对象,那么 this 将指向全局对象(global object)。
1
2
3
s = makePerson("Simon", "Willison");
var fullName = s.fullName;
fullName(); // undefined undefined
使用关键字 this 改进
1
2
3
4
5
6
7
8
9
10
11
function Person(first, last) {
this.first = first;
this.last = last;
this.fullName = function() {
return this.first + ' ' + this.last;
}
this.fullNameReversed = function() {
return this.last + ', ' + this.first;
}
}
var s = new Person("Simon", "Willison");
  • 单独调用fullName() 时会产生相同的问题,this指向全局变量,undefined
  • new,它和 this 密切相关。它的作用是创建一个崭新的空对象,然后使用指向那个对象的 this 调用特定的函数。注意,含有 this 的特定函数不会返回任何值,只会修改 this 对象本身。new 关键字将生成的 this 对象返回给调用方,而被 new 调用的函数成为构造函数。习惯的做法是将这些函数的首字母大写,这样用 new 调用他们的时候就容易识别了。
再次改进
1
2
3
4
5
6
7
8
9
10
11
12
function personFullName() {
return this.first + ' ' + this.last;
}
function personFullNameReversed() {
return this.last + ', ' + this.first;
}
function Person(first, last) {
this.first = first;
this.last = last;
this.fullName = personFullName;
this.fullNameReversed = personFullNameReversed;
}
(最佳的方案)原型链
1
2
3
4
5
6
7
8
9
10
function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.fullName = function() {
return this.first + ' ' + this.last;
}
Person.prototype.fullNameReversed = function() {
return this.last + ', ' + this.first;
}
  • 当你试图访问一个 Person 没有定义的属性时,解释器会首先检查这个 Person.prototype 来判断是否存在这样一个属性。所以,任何分配给 Person.prototype 的东西对通过 this 对象构造的实例都是可用的。

在程序中的任何时候修改原型(prototype)中的一些东西

1
2
3
4
5
6
7
s = new Person("Simon", "Willison");
s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function
Person.prototype.firstNameCaps = function() {
return this.first.toUpperCase()
}
s.firstNameCaps(); // SIMON

可以给 JavaScript 的内置函数原型(prototype)添加东西。让我们给 String 添加一个方法用来返回逆序的字符串:

  • PS: 这个方法可以随时制作自定义的方法
1
2
3
4
5
6
7
8
9
10
11
var s = "Simon";
s.reversed(); // TypeError on line 1: s.reversed is not a function
String.prototype.reversed = function() {
var r = "";
for (var i = this.length - 1; i >= 0; i--) {
r += this[i];
}
return r;
}
s.reversed(); // nomiS

定义新方法也可以在字符串字面量上用(string literal)。

1
"This can now be reversed".reversed(); // desrever eb won nac sihT


内部函数(可以访问父函数作用域中的变量,一个减少使用全局变量的好方法)

嵌套函数:可以访问父函数作用域中的变量

1
2
3
4
5
6
7
function betterExampleNeeded() {
var a = 1;
function oneMoreThanA() {
return a + 1;
}
return oneMoreThanA();
}
  • 如果某个函数依赖于其他的一两个函数,而这一两个函数对你其余的代码没有用处,你可以将它们嵌套在会被调用的那个函数内部,这样做可以减少全局作用域下的函数的数量,这有利于编写易于维护的代码。

闭包(返回外部函数)

1
2
3
4
5
6
7
8
9
function makeAdder(a) {
return function(b) {
return a + b;
}
}
var x = makeAdder(5);
var y = makeAdder(20);
x(6); // ?
y(7); // ?
  • makeAdder创建了一个新的 adder 函数,这个函数自身带有一个参数,它被调用的时候这个参数会被加在外层函数传进来的参数上。
  • 与内嵌函数不同的是,外部函数被返回了,那么常识告诉我们局部变量“应该”不再存在。但是它们却仍然存在——否则 adder 函数将不能工作。也就是说,这里存在 makeAdder 的局部变量的两个不同的“副本”——一个是 a 等于5,另一个是 a 等于20。
1
2
x(6); // 返回 11
y(7); // 返回 27

每当 JavaScript 执行一个函数时,都会创建一个作用域对象(scope object),用来保存在这个函数中创建的局部变量。它和被传入函数的变量一起被初始化。这与那些保存的所有全局变量和函数的全局对象(global object)类似,但仍有一些很重要的区别,第一,每次函数被执行的时候,就会创建一个新的,特定的作用域对象;第二,与全局对象(在浏览器里面是当做 window 对象来访问的)不同的是,你不能从 JavaScript 代码中直接访问作用域对象,也没有可以遍历当前的作用域对象里面属性的方法。

所以当调用 makeAdder 时,解释器创建了一个作用域对象,它带有一个属性:a,这个属性被当作参数传入 makeAdder 函数。然后 makeAdder 返回一个新创建的函数。通常 JavaScript 的垃圾回收器会在这时回收 makeAdder 创建的作用域对象,但是返回的函数却保留一个指向那个作用域对象的引用。结果是这个作用域对象不会被垃圾回收器回收,直到指向 makeAdder 返回的那个函数对象的引用计数为零。

##### 闭包(Closure)补充知识
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

1
2
3
4
5
var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。

1
2
3
4
  function f1(){
    var n=999;
  }
  alert(n); // error
  • 闭包的用途
1
2
3
4
5
6
7
8
9
function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  • 思考题
1
2
3
4
5
6
7
8
9
10
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()()); //The Window
1
2
3
4
5
6
7
8
9
10
11
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()()); //My Object

内存泄漏(不要在匿名内部函数中使用变量、添加另外一个闭包)

解决因闭包而引入的循环引用:

  1. 不要在匿名内部函数中使用变量
  2. 添加另外一个闭包
1
2
3
4
5
6
function addHandler() {
var el = document.getElementById('el');
el.onclick = function() {
el.style.backgroundColor = 'red';
}
}

这段代码创建了一个元素,当它被点击的时候变红,但同时它也会发生内存泄露。为什么?因为对 el 的引用不小心被放在一个匿名内部函数中。这就在 JavaScript 对象(这个内部函数)和本地对象之间(el)创建了一个循环引用。

解决办法1:不要使用e1变量

1
2
3
4
5
function addHandler(){
document.getElementById('el').onclick = function(){
this.style.backgroundColor = 'red';
};
}

解决办法2:添加另外一个闭包

1
2
3
4
5
6
7
8
9
function addHandler() {
var clickHandler = function() {
this.style.backgroundColor = 'red';
};
(function() {
var el = document.getElementById('el');
el.onclick = clickHandler;
})();
}

this

  • Java属于编译期绑定,而JS属于 运行期绑定
  • this和它声明环境无关,而完全取决于他的执行环境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//读以下代码之前,必须先阅读《哈利·波特》原著。(笑)
var name = '罗恩';
var aaa = {
name: '哈利',
say: function () {
console.log(this.name);
}
}
var bbb = {
name: '赫敏',
say: aaa.say
}
var ccc = aaa.say;
aaa.say(); //哈利
bbb.say(); //赫敏
ccc(); //罗恩

bbb把aaa对象的say方法引用过来,引用的是一个方法而非一个对象,而aaa.say存储的是一个匿名函数,所以这种写法和以下代码并没有什么区别。

1
2
3
4
5
6
var bbb = {
name: '赫敏',
say: function () {
console.log(this.name);
}
}
  • 特殊情况:
    和``` setInterval ```
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ```javascript
    var aaa = {
    name: '哈利',
    getName: function () {
    setTimeout(function(){
    console.log(this.name);
    },100)
    }
    }

原来三行的输出会是什么?

答案:3个罗恩。
也就是说,三次this,指代的都是window对象。

稍微改写一下这个方法:

1
2
3
4
5
6
7
8
getName: function () {
//在setTimeout外存储this指代的对象
var that = this;
setTimeout(function(){
//this.name变成了that.name
console.log(that.name);
},100)
}

输出就又正常了。


ES6

类

使用 extends 创建子类

构造器:

  • 构造器方法是一个特殊的类方法,其用于创建和初始化对象(用该类生成的)。一个类只能拥有一个名为 constructor 的方法,否则会抛出 SyntaxError 异常。

extends 关键字可以用在类声明或者类表达式中来创建一个继承了某个类的子类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
// 'Mitzie barks.'
d.speak();
(function() {
var el = document.getElementById('el');
el.onclick = clickHandler;
})();
}

同样也可以用于原有的原型继承的“类”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Animal (name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(this.name + ' makes a noise.');
}
class Dog extends Animal {
speak() {
super.speak();
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
d.speak();


使用 super 引用父类

super 关键字可以用来调用其父类的构造器或者类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + ' roars.');
}
}


文档对象模型(DOM)

enter image description here


浏览器对象模型(BOM)


Javascript写成类插件

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
28
29
30
;
(function($) {
var Drawingboard = function(settings) {
var settings = settings || {}
var defaultSettings = {
lineWidth: 1
}
this.settings = $.extend(defaultSettings, settings);
this.abc = "abc";
}
Drawingboard.prototype = {
func1: function() {
console.log("this.abc----", this.abc);
},
func2: function() {
var test = this;
console.log("this.abc", this.abc); //打印abc
var test1 = $("h3").click(function() {
console.log(test.abc); //打印abc;没有赋值var test =this,打印undefined
test.abc = "bbb";
console.log(test.abc); //打印bbb
test.func1(); //打印bbb
});
}
}
window.Drawingboard = Drawingboard;
var canvas = new Drawingboard();
canvas.func2();
})(jQuery);

JavaScript常错

getElementById 获取变量

但如果事先定义一个变量,例如

1
2
var itemId=label1;
var item=document.getElementById('itemId');//双引号一样

然后就会报错,说item为null。
如果去掉引号就好了。。
即:

1
2
var itemId=label1;
var item=document.getElementById(itemId);//没有引号就好了

不加引号,这个itemid就是变量,加上引号,这就是字符串常量。电脑就去找ID为ItemId的元素。自然是null

javascript 陷阱集

  • 考作用域
1
2
3
4
5
6
7
(function() {
var b = 5;
var a = b;
b = 6;
console.log(a,b);
//5 6
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var g = 0;
function f() {
    // 这里面就形成了一个方法作用域, 能够保护其中的变量不能被外部访问
    // 方法作用域能够访问全局作用域
    var a = 1;
    console.log(g);
    // 嵌套方法作用域
    function ff() {
        // 这里面再度形成了一个方法作用域
        // 其中可以访问外部的那个方法作用域
        var aa = 2;
        console.log(a);
    }
    // 出了 ff 的作用域就不能访问其中的东西了
    // console.log(aa); // 报错 ReferenceError: aa is not defined
}
f();
// console.log(a); // 报错 ReferenceError: a is not defined
  • 考声明提前
1
2
3
4
5
6
7
8
9
10
11
//考声明提前
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();
  • 考 this
1
2
3
4
5
6
7
8
9
10
11
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
getFullname: function() {
return this.fullname;
}
};
console.log(obj.getFullname()); //Colin Ihrig
var test = obj.getFullname; //John Doe
console.log(test());
  • 制造干扰因素的版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
},
getFullname: function() {
return this.fullname;
}
};
console.log(obj.prop.getFullname()); //Aurelio De Rosa
console.log(obj.getFullname()); //Colin Ihrig
var test = obj.prop.getFullname; //John Doe
console.log(test());
  • 分号陷阱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//分号陷阱
function fn(){
return {
x:1
};
} //{x:1}
function fn(){
return
{
x:1
};
}
console.log(fn()) //undefined
  • 小数相加
1
2
3
4
//不要相信js的符点运算结果,但是整数是可依赖的
0.1 + 0.2 不等于 0.3 //0.30000000000000004
可用如下
(0.1*10 + 0.2*10)/10
Yoko Kuok

Yoko Kuok

6 日志
5 标签
GitHub
© 2017 Yoko Kuok
由 Hexo 强力驱动
主题 - NexT.Mist