JiM-W

keep Moving


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

PHP base

发表于 2016-12-11 | 分类于 php

PHP 基础语法(运行在服务器端的脚本语言)

1 定义变量 $str = “strings” \$num = 4 ; \$Bool = true ; \$float = 4.5;数据类型包括字符串,数值,布尔类型,浮点类型

2 定义数组 $arr = array( ) ,php提供了 array这个函数帮助我们去定义一个数组;

$arr = array (2,”hello world”,4) 这是索引数组,可以通过下标进行访问,注意array函数是关键

$arr =array (“name”=>”Jhon”,”age”=>23,”address”=>”china”) 这是关联数组,类似于js的键值对;

4 echo 只能输出简单数据类型; print_r( ):可以输出复杂数据类型,比如数组;var_dump( )可以输出详细的信息,比如数组和对象

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
46
47
<?php
header("Content-Type:text/html;charset=utf-8");
$arr = array("name"=>"jhon","age"=>5);
/*echo: 可以输出简单数据类型*/
// echo array["name"];
// echo array["age"];
echo $arr["name"];
echo "<br/>";
echo $arr["age"];
echo "<br/>";
echo $arr;
echo "<br/>";
echo "next print";echo "<br/>";
/*print_r()可以输出复杂数据类型*/
print_r($arr["name"]);
echo "<br/>";
print_r($arr["age"]);
echo "<br/>";
print_r($arr);
echo "<br/>";
echo "next dump";echo "<br/>";
/*var_dump()输出详细信息*/
var_dump($arr["name"]);
echo "<br/>";
var_dump($arr["age"]);
echo "<br/>";
var_dump($arr);
echo "<br/>";
?>
//输出结果如下:
/*jhon
5
Array
next print
jhon
5
Array ( [name] => jhon [age] => 5 )
next dump
string 'jhon' (length=4)
int 5
array
'name' => string 'jhon' (length=4)
'age' => int 5
*/

(对于布尔类型,echo print_r( ) 输出true为1,对于false 则不会输出内容 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
header("Content-Type:text/html;charset=utf-8");
$flag1 = false ;
echo $flag1;//什么都不会输出
print_r( $flag1);//什么都不输出
var_dump($flag1);//boolean false
$flag2 = true ;
echo $flag2;//1
print_r($flag2);//1
var_dump($flag2);//boolean true
$flag3 = 4 ;
echo $flag3 ;//4
$flag4 = "hello";
echo $flag4;//hello
$arr = array("name","Jhon");
echo $arr;//Array
echo {"name":"Jim","age":12};//直接报错
?>

5 php文件和HTML文件的关系,php文件中可以直接写HTML代码,会被解析成相应的标签,但是HTML文件却不能识别php代码,同样如果想在php代码中向页面输出标签,需要用 echo 或者print_r( ) 向页面输出标签;

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div{
width:100px;
height:100px;
background-color:red;
}
</style>
</head>
<body>
<div>欢迎</div>
<?php
header("Content-Type:text/html;charset=utf-8");
//这个代码是在服务端运行的,
//我就可以在这里 从数据库取数据. 输出到页面上面
echo "Jhon";
echo "<P>你好</p>";
?>
</body>
</html>
1
2
3
4
5
6
<?php
// <div>这个div在php里面</div> 如果HTMl代码出现在php代码块里面会直接报错
//这个代码是在服务端运行的,
//我就可以在这里 从数据库取数据. 输出到页面上面
echo "Jhon";
?>

6 PHP header()函数

1
header(string,replace,http_response_code)
参数 描述
string 必需。规定要发送的报头字符串。
replace 可选。指示该报头是否替换之前的报头,或添加第二个报头。默认是 true(替换)。false(允许相同类型的多个报头)。
http_response_code 可选。把 HTTP 响应代码强制为指定的值。即返回给客户端的数据格式

PHP文件中header的作用,给客户端一个响应头:1)规定文件以什么格式解析;2)charset规定客户端浏览器以什么方式解析编码 对文件编码解析 方式; 3)charset需要设置编码方式 的和文件的自身编码 方式一致,否则浏览器解析将出现乱码;4)Refresh可以服务器给客户端的相应;5)解决乱码问题 服务器到客户端,通过header头进行规定,

1
2
3
header("Content-Type:text/javascript;charset=utf-8");//php文件将text解析成javascript,返回给浏览器,然后浏览器进行解析;浏览器文件编码解析方式是utf-8
header("Content-Type:text/html;charset=GBK");//php文件将text解析成HTML,返回给浏览器,浏览器以html格式将其解析;浏览器文件编码解析方式是GBK;
header("Refresh:5;url=http://m.youyuanwang")

7 数组的方法,在php中没有length属性来获取数组的长度,那么如何获取数组的长度呢?count 方法

1
2
3
count($arr1) : 求数组arr1的长度 返回整形数值
in_array("value",$arr2) : arr2首先得是一个普通数组,可以判断在数组arr2中是否存在value,返回布尔类型值;
array_key_exists("vale",$arr3):arr3首先得是一个关联数组,可以判断数组arr3中是否存在value,返回布尔类型值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
header("Content-Type:text/html;charset=utf-8");
$arr1 = array("name",2,"hello");//定义普通数组
$arr2 = array("name"=>"jhon","age"=>17,"gender"=>"male");//定义关联数组
//求数组的长度,返回数值类型
echo "getArrLength";
var_dump ( count($arr1) );//int 3
var_dump ( count($arr2) );//int 3
//求数组中是否存在某一个,返回布尔类型的值,只能用于普通数组
echo "getin-array";
var_dump (in_array("name",$arr1));// boolean true
var_dump (in_array("name",$arr2) );//boolean false
//判断数组中是否存在某个key,返回布尔类型数值,只适用于关联数组
echo "array_key_exists";
var_dump ( array_key_exists("name",$arr1));//boolean false
var_dump( array_key_exists("name",$arr2));//boolean true
?>

7 表单处理 注释:form 元素是块级元素,其前后会产生折行。

​ 1)HTML代码

1
2
3
4
表单name属性的是用来提供给服务端接收所传递数据而设置的;
表单action属性设置接受数据的处理程序,比如action="progress_form.php",表示用progress_form.php程序处理form;
表单method属性设置发送数据的方式,method="get" method="post",设置数据的上传到后台的的方式;
超链接和地址栏默认 method="get" 数据提交方式,如果想要上传文件,必须:form表单设置enctype="multipart/form-data",method="post"

​ 2)PHP代码获取用户上传数据

1
2
3
$_GET 接受HTML代码部分以get方式的传值,比如超链接,地址栏,form表单设置method="get";$_GET是一个关联数组
$_POST 接受HTML代码部分以post方式的传值,比如form表单设置method="post";$_POST 是一个关联数组
$_FILES 接受文件上传

​ 3) \$_POST 客户端向服务器发送请求的时候,发送的信息不会在地址栏显示;变量是一个数组,内容是由 HTTP POST 方法发送的变量名称和值。并且对发送信息的量也没有限制。

例子

地址栏 scheme://host.domain:post/pash/filename

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form action="login.php" method="post">
昵称: <input type="text" name="username"> <br><br> //假设输入 Jhon
密码:<input type="password" name="psw"><br><br> //假设输入 123456
<input type="submit" value="post提交">
</form>
<?php
header("Content-Type:text/html;charset=utf-8");
//接收数据
var_dump($_POST); //输出$_POST,查看$_POST的详细内容;
$username=$_POST['username'];
$password=$_POST['password'];
?>
//$_POST = array("username"=>"John","psw"=>"12345"),$_POST是一个关联数组,该数组内存放着用户上传的数据
//地址栏显示:http://127.0.0.1/02-php/02-get-post/03-loginphp.php
//127.0.0.1 这是我的域名 02-php/02-get-post/03-loginphp.php 这是我的电脑服务器处理程序的存储路径

​ $_GET 客户端向服务器发送请求的时候,发送的数据在地址栏的后面显示出来,\$_GET 变量用于收集来自 method=”get” 的表单中的值。该变量是一个数组,内容是由 HTTP GET 方法发送的变量名称和值。对发送信息量有限制(最多 100 个字符)。

1
2
<a href="01get.php?username=zhangsan&age=11">get 方式提交</a>
地址栏显示:http://127.0.0.1/02-php/02-get-post/01-getphp.php?username=zhangsan&age=11
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form action="login.php" method="get">
昵称: <input type="text" name="username"> <br><br> //假设输入 Jhon
密码:<input type="password" name="psw"><br><br> //假设输入 123456
<input type="submit" value="get提交">
</form>
<?php
header("Content-Type:text/html;charset=utf-8");
//接收数据
var_dump($_GET); //输出$_GET ,查看$_GET的详细内容
$username=$_GET['username'];
$password=$_GET['psw'];
?>
//$_GET = array("username"=>"John","psw"=>"12345"),$_POST是一个关联数组,该数组内存放着用户上传的数据
//地址栏显示:http://127.0.0.1/02-php/02-get-post/03-loginphp.php?username=lupan&psw=123456
?username=lupan&psw=123456 这是用户上传的数据,get方式上传数据可以直接在地址栏看到

​ $_FILES input type=”file” \$FILES 将会包含标签的相关信息;

标签的 enctype 属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,必须使用
“multipart/form-data”。

  • 文件上传form必须 用method=”post”方法,get方法无法上传file数据
  • form必须 有 enctype=”multipart/form-data 属性,如果没有设置该属性,无法上传数据;
  • input type 类型必须 file; 这三者同时满足了才能 $_FILES才存在 。否则 var_dump(\$_FILES) 结果为 empty;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form action="01-filesupload.php" method="post" enctype="multipart/form-data" >
<input type="file" name="lifephoto"/>
<input type="submit" value="提交"/>
</form>
<?php
header("Content-Type:text/html;charset=utf-8");
var_dump($_FILES);
//$_FILES是一个关联数组,(二维数组)
/*输出结果如下:
array
'lifephoto' =>
array
'name' => string 'DSC_0002.JPG' (length=12) //文件名
'type' => string 'image/jpeg' (length=10) //文件类型
'tmp_name' => string 'D:\wamp\tmp\php3971.tmp' (length=23) //临时存储地址
'error' => int 0
'size' => int 1672087
*/
$tmp_name = $_FILES['lifephoto']['tmp_name'];
$fileName =$_FILES['lifephoto']['name'];
$newFile = './'.time().'.jpg'
move_uploaded_file($tmp_name,$newFile);
?>
//地址栏显示:http://127.0.0.1/02-php/03-files/01-filesupload.php
1
move_uploaded_file($tmp_name,"images/".$fileName); 该方法可以用来改变用户上传的文件存储的地址。

8 file_get_contents() 函数把整个文件读入一个字符串 中。

和 file() 一样,不同的是 file_get_contents() 把文件读入一个字符串。

file_get_contents() 函数是用于将文件的内容读入到一个字符串中的首选方法。如果操作系统支持,还会使用内存映射技术来增强性能。

1
file_get_contents(path,include_path,context,start,max_length)
参数 描述
path 必需。规定要读取的文件。
include_path 可选。如果也想在 include_path 中搜寻文件的话,可以将该参数设为 “1”。
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 null,则忽略。
start 可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 新加的。
max_length 可选。规定读取的字节数。该参数是 PHP 5.1 新加的。

该方法是服务器读取数据的常用方法,然后可以返回数据给到客户端。

注意:

  • php每一行代码的最后必须有分号 “ ; ” ,必须在每一行作为结束;
  • 单引号里面的变量不会被执行,会被当做字符串运行,双引号里面的变量会被执行,可以解析成变量代表的值;
  • echo print_r()可以向页面中输出HTMl代码,但是var_dump()向页面输出的是
    标签
  • php里面的字符串拼接用的是 “ . ” 等价于js中的 “ + ”,会将结果转化为字符串;
  • php代码块里面不能出现HTML代码,会报错;

ES6新特性 箭头函数

发表于 2016-12-07 | 分类于 ES6

ES6新特性 箭头函数

1
2
3
4
5
6
7
8
9
10
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: => { return expression; }
// 如果只有一个参数,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
// 无参数的函数需要使用圆括号:
() => { statements }

函数简写: 如果函数值计算一个表达式并返回它的值,那么return和花括号都可以省略,并将待计算的额表达式紧跟在参数列表之后

1 语法:如果没有用{ } 将函数体括起来,那么返回值就是函数体执行的结果;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var fn = () => 1+2 ;
console.log(fn);
console.log(fn());//3
//------------------------------------------------------------------
var fn1 = (value) => value ;//等价于
// var fn1 = value => value ; 如果只传递一个参数,那么括号是可以不写的
console.log(fn1);
console.log(fn1(2));//2
//等价于
var fn1 = function(value){
return value ;
}
//----------------------------------------------------------------------
var fn2 = (a,b) => a+b ;
console.log(fn2 );
console.log(fn2(2,3));//5

2 如果使用{ }将函数体括起来,默认返回值undefined;

1
2
3
4
5
6
7
8
var fn1 = (value) => {value} ;
console.log(fn1);
console.log(fn1(2));//undefined
//等价于
var fn1 = function(value){
value ;
}
//函数执行完毕默认返回值是undefined ;
1
2
3
4
5
6
7
8
9
10
11
var fn = () => {return 1+2} ;
console.log(fn);
console.log(fn());//3
//----------------------------------------------------------
var fn1 = (value) => {return value} ;
console.log(fn1);
console.log(fn1(2));//2
//----------------------------------------------------------
var fn2 = (a,b) => {return a+b} ;
console.log(fn2 );
console.log(fn2(2,3));//5

3 如何用箭头函数自定义对象 需要用小括号将花括号包起来;

1
2
3
4
5
var obj = (name,age) => ({
name : name ,
age:age
});
console.log( obj("jhon",13));

等价于

1
2
3
4
5
6
var obj = function(name,age){
return {
name:name,
age:age
}
}

4 箭头函数的优势

4.1 更简短的函数书写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var arr=["name",13,"Jim"];
var newArr = arr.map(function(item){ //注意map函数没有返回值,默认返回值是undefined
return item.length ;
});
//等价于
//var newArr = arr.map(item => item.length )
console.log(newArr);
//-----------------------------------------------------------------------
var Flatten = [[1,2],[4,6],[7,9]]
// var newFaltten = Flatten.reduce(function(a,b){
// return a.concat(b);
// },[])
var newFaltten = Flatten.reduce(
(a,b) => a.concat(b),
[]
);

4.2 不绑定this

1
2
3
4
5
6
7
8
9
10
11
//看下这个demo setInterval中的函数this默认指向是 window ,所以this.age获取不到值,等价于undefined++,结果是NaN;
function Person (){
this.age = 0 ;
setInterval(function(){
console.log(this);
this.age++ ;
//点操作优先级最高,相当于先给window对象添加了一个age属性,但是未赋值,默认值是undefined
console.log(this.age);
},1000)
}
var person = new Person();
1
2
3
4
5
6
7
8
9
10
11
//正常我们解决这个问题的办法如下
function Person (){
this.age = 0 ;
var _this = this
setInterval(function(){
console.log(_this);
_this.age++ ;
console.log(_this.age);
},1000)
}
var person = new Person();

如果我们使用箭头函数 箭头函数则会捕获其所在上下文的 this值,作为自己的 this 值

1
2
3
4
5
6
7
8
9
10
function Person (){
this.age = 0 ;
setInterval(() => {
console.log(this);
this.age ++ ;
console.log(this.age);
},1000);
}
var person = new Person();

5 箭头函数没有自己的 arguments对象

1
2
var fn = () => arguments ; //arguments在箭头函数里面没有任何意义
console.log(fn());// arguments is not defined
1
2
3
//原先的函数声明都是有个arguements对象的
var fn = function(){return arguments}
console.log(fn());

6 箭头函数可以用作对象的方法(箭头函数内部没有定义this指向,其会根据函数运行确定this指向)

1
2
3
4
5
6
7
'use strict'
var name = "Jim";
var obj= {
name : 'Jhon',
fn :() => this.name
}
console.log(obj.fn());

对比理解下:箭头函数的this指向其运行环境外围的作用域;

1
2
3
4
5
6
7
var person = {
name: "Nicholas",
sayName() {
console.log(this.name);
}
};
personn.sayName() ;//Nicholas
1
2
3
4
5
6
var person = {
name: "Nicholas",
sayName:()=> {
console.log(this.name);
}
personn.sayName() ;//undefined

AngularJs自定义指令中的controller link和compile

发表于 2016-12-03 | 分类于 javascript

1 compile、postlink、 link、 controller

1.1 compile function

  • compile函数:当一个angular应用程序初始化的时候被执行一次,并且只执行一次
  • compile函数中不包括作用域的操作以及数据绑定,以及监听器的绑定

    Do:

  • Manipulate markup so it serves as a template to instances (clones).

    Do not

  • Attach event handlers.

  • Inspect child elements.
  • Set up observations on attributes.
  • Set up watches on the scope.

1.2 Post-link function

When the post-link function is called, all previous steps have taken place - binding, transclusion, etc.

This is typically a place to further manipulate the rendered DOM.

Do:

  • Manipulate DOM (rendered, and thus instantiated) elements.
  • Attach event handlers.
  • Inspect child elements.
  • Set up observations on attributes.
  • Set up watches on the scope.

1.3 Controller function

Each directive’s controller function is called whenever a new related element is instantiated.

Officially, the controller function is where one:

  • Defines controller logic (methods) that may be shared between controllers.
  • Initiates scope variables.

Again, it is important to remember that if the directive involves an isolated scope, any properties within it that inherit from the parent scope are not yet available.

Do:

  • Define controller logic
  • Initiate scope variables

Do not:

  • Inspect child elements (they may not be rendered yet, bound to scope, etc.).
    1.4 Pre-link function

Each directive’s pre-link function is called whenever a new related element is instantiated.

As seen previously in the compilation order section, pre-link functions are called parent-then-child, whereas post-link functions are called child-then-parent.

The pre-link function is rarely used, but can be useful in special scenarios; for example, when a child controller registers itself with the parent controller, but the registration has to be in a parent-then-child fashion (ngModelController does things this way).

Do not:

Inspect child elements (they may not be rendered yet, bound to scope, etc.).

2 各个作用搬运完毕,看下angularjs的生命周期

2.1 编译阶段

在编译阶段,AngularJS会遍历整个HTML文档并根据JavaScript中的指令定义来处理页面上声明的指令。每一个指令的模板中都可能含有另外一个指令,另外一个指令也可能会有自己的模板。当AngularJS调用HTML文档根部的指令时,会遍历其中所有的模板,模板中也可能包含带有模板的指令.一旦对指令和其中的子模板进行遍历或编译,编译后的模板会返回一个叫做模板函数的函数。我们有机会在指令的模板函数被返回前,对编译后的DOM树进行修改。

2.2 第二个阶段是链接阶段:链接函数来将模板与作用域链接起来;负责设置事件监听器,监视数据变化和实时的操作DOM.链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义了时,编译函数会重载链接函数.

2.3 走一个demo看下效果

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
46
47
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-app = 'myApp'>
<my-directive></my-directive>
<script src="../libs/angular.js"></script>
<script>
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
//controller函数可以传入参数
console.log(arguments);
console.log('this is controller');
},
compile:function(){
console.log(arguments);
console.log("this is compile");
return {
pre : function(){
console.log(arguments);
console.log("this is pre");
},
post : function(){
console.log(arguments);
console.log("this is post");
},
}
},
link : function(){
console.log(arguments);
console.log("this is link");
}
}
})
</script>
</body>
</html>

控制台输出如下(关于每个函数的arguments这里不再写了,主要是为了看下每个函数要求传入的参数为何)

1
2
3
4
this is compile
this is controller
this is pre
this is post

我们发现link并没有被执行,因为link被compile函数覆盖了

简化directive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
myApp.directive('myDirective',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
console.log(arguments);
console.log('this is controller');
},
link : function(){
console.log(arguments);
console.log("this is link");
}
}
})
1
2
this is controller
this is link

这个时候我们发现controller和link都可以执行了,那么我们在实际应用中应该使用哪个?

  • 指令的控制器和link函数可以进行互换。控制器主要是用来提供可在指令间复用的行为,但链接函数只能在当前内部指令中定义行为,且无法在指令间复用.link函数可以将指令互相隔离开来,而controller则定义可复用的行为。
  • 如果我们希望将当前指令的API暴露给其他指令使用,可以使用controller参数,否则可以使用link来构造当前指令元素的功能性。如果我们使用了scope.$watch()或者想要与DOM元素做实时的交互,使用链接会是更好的选择。

2.4 子级指令的所有 link function :包括 pre 和 post 两个link都会在父级的post link之前被执行,我们用的link function 其实是post link的快捷方式罢了

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<body ng-app = 'myApp'>
<div parent>
<div child></div>
</div>
<div parent1>
<div child1></div>
</div>
<script src="../libs/angular.js"></script>
<script>
var myApp = angular.module('myApp',[]);
myApp.directive('parent',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
console.log('parent controller');
},
compile:function(){
console.log("parent compile");
return {
pre : function(){
console.log("parent pre");
},
post : function(){
console.log("parent post");
},
}
},
}
})
myApp.directive('child',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
console.log('child controller');
},
compile:function(){
console.log("child compile");
return {
pre : function(){
console.log("child pre");
},
post : function(){
console.log("child post");
},
}
},
}
})
myApp.directive('parent1',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
console.log('parent1 controller');
},
compile:function(){
console.log("parent1 compile");
return {
pre : function(){
console.log("parent1 pre");
},
post : function(){
console.log("parent1 post");
},
}
},
}
})
myApp.directive('child1',function(){
return {
restrict : "EA",
controller:function(){
// controller:function($scope, $element, $attrs, $transclude){
console.log('child1 controller');
},
compile:function(){
console.log("child1 compile");
return {
pre : function(){
console.log("child1 pre");
},
post : function(){
console.log("child1 post");
},
}
},
}
})
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
parent compile
child compile
parent1 compile
child1 compile
parent controller
parent pre
child controller
child pre
child post
parent post
parent1 controller
parent1 pre
child1 controller
child1 pre
child1 post
parent1 post

友情链接一个so

ES6 let const

发表于 2016-12-01 | 分类于 ES6

ES6变量声明 let const

1 let声明

1.1 let声明的变量和var声明变量一样,都可以从父级作用域获取变量

1
2
3
4
5
6
7
8
let x = 9 ;//全局声明 let x ;
~function fn(){
console.log(x);//9 可以访问父作用域内let声明的变量
}();
{
x = x + 3 ; //
console.log(x);//12
}

1.2 let 声明的变量必须 先声明 在 使用 , 所有在声明之前的使用都会报错; 在同一个作用域内用let声明的变量不允许重复(暂时性死区) var却可以在同一作用域内重复声明同名变量 ;

1
2
3
4
5
{
var b = 8 ;
var b = 999;
console.log(b);//999 var声明变量可以重复声明名称相同的变量
}
1
2
3
4
5
6
let x = 9 ;
{
let x = x + 3 ; //Uncaught ReferenceError: x is not defined
//对于let在一个作用域内,必须先声明在使用,这里需要注意,赋值运算是从右向左进行的,
console.log(x);
}

2 const声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 1 const声明,可以声明一个常量,该常量在声明的同时必须初始化,如果不初始化会报错,
2 const声明可以声明一个复杂数据类型,同时该复杂数据类型也必须初始化
3 const声明本质上其实是保证所声明的变量指向的内存地址是不能变化的,比如声明基本数据类型,声明之后不可改变
如果声明一个复杂数据类型,同样不能重新赋值
*
* */
// -----------------------------
// 基本数据类型,声明之后不能重新赋值,
const p = 9 ;
p = 8 ; //Uncaught TypeError: Assignment to constant variable.
// --------------------------------
// 复杂数据类型,声明后该变量指向内存中的指针不能再修改,但是复杂数据类型内部的数据结构还是可变的
const o = {};//指向一个地址,改地址存放一个空的对象
o.name = "Jhon";//内部数据结构是可变的
console.log(o);
o = {};//Uncaught TypeError: Assignment to constant variable.

Nodejs Express

发表于 2016-11-30 | 分类于 nodejs

1 Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。[express作者jk]

利用defineProperty获取闭包内部数据

发表于 2016-11-30 | 分类于 javascript

利用defineProperty获取闭包内部数据

1 defineProperty的使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
Object.defineProperty(obj,property,{
value:"属性值",
writable:false,//控制属性是否可以重新赋值
configurable:false,//控制属性是否可以被删除
enumerable:false,//是否可枚举
get:function(){
return this.propertyValue;
},
set:function(value){
this.propertyValue = value;
}
})

2 利用给定接口获取闭包内部数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var o = (function() {
var person = {
name: 'Vincent',
age: 24,
};
return {
run: function(k) {
return person[k];
},
}
}());
//在不改变上面的代码情况下, 怎么得到原有的 person 对象?
//解决:
Object.defineProperty(Object.prototype, 'self',
{
get: function() {
return this;
},
configurable: true
});
o.run('self'); // 输出 person

the difference between null and undefined

发表于 2016-11-29 | 分类于 javascript

1 typeof的使用;这是一个运算符,不是方法

1.1检测数据类型,返回的结果是一个字符串类型。有六种可能:number boolean string object function undefined

注意typeof(null) 返回的是 : object

typeof 运算符来判断一个值是否在某种类型的范围内。可以用这种运算符判断一个值是否表示一种原始类型:如果它是原始类型,还可以判断它表示哪种原始类型。ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String

1.1.1 在ES6 之前,typeof可以随心所欲的时候,基本上不会报错

1
console.log(typeof a);//undefined 即使 a 在之前为进行任何的声明
1
console.log( a);//a is not defined 报错

1.1.2 但是在ES6 之后引入了let和const之后 typeof 就需要掂量一下自己咯,let声明的变量,在所声明的作用域中,必须在使用之前进行声明 ,其实这是一个好的趋势,可以形成严谨良好的编程习惯;

1
2
console.log(typeof a);//Uncaught ReferenceError: a is not defined
let a;
1
2
let a;
console.log(typeof a);//undefined

1.2 typeof 可以用于被声明 或者未被声明 的变量;但是未被声明 的变量不能用其他运算符运算,之外的其他运算符的话,会引起错误,因为其他运算符只能用于已声明的变量上。

1
2
3
4
5
6
7
8
9
<script>
var exp1 ;
console.log(typeof exp1);//undefined
console.log(typeof exp2);//undefined
console.log(exp1 == undefined);//true
console.log(exp2 == undefined);//报错
console.log(typeof exp1 == 'undefined');//true
console.log(typeof exp2 == 'undefined');//true typeof运算符可以用于未被声明的变量
</script>

1.3 对于基本数据类型(Number Boolean String null undefined) 以及引用类型 object的typeof值

1.3.1类 : Object Function Array String Boolean Number Date ;这些未初始化为实例的类的typeof类型为function

1
2
3
4
5
6
7
8
9
10
11
function test (){ }
console.log(Object);//function Object() { [native code] }
console.log(typeof Object);//function
console.log(Array);//function Array() { [native code] }
console.log(typeof Array);//function
console.log(Function);//function Function() { [native code] }
console.log(typeof Function);//function
console.log(String);//function String() { [native code] }
console.log(typeof String);//function
console.log(test);//function test(){ }
console.log(typeof test);//function

1.3.2 对象的创建方式是用关键字 new 后面跟上实例化的类的名字,当将一个函数通过new实例化之后,那么就创建了一个对象

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 test (){ }
var obj = new test();
console.log(obj.constructor);//function test(){}
console.log(obj);//test{}
console.log(typeof obj);//Object
var obj1 = new Array();
console.log(obj1.constructor);//function Array() { [native code] }
console.log(obj1);//[]
console.log(typeof obj1);//Object
var obj2 = new Function();
console.log(obj2.constructor);//function Function() { [native code] }
console.log(obj2);//function anonymous() {}
console.log(typeof obj2);//function
var obj3 = new String();
console.log(obj3.constructor);//function String() { [native code] }
console.log(obj3);//String {length: 0, [[PrimitiveValue]]: ""}
console.log(typeof obj3);//object
var obj4 = new Object();
console.log(obj4.constructor);//function Object() { [native code] }
console.log(obj4);//Object {}
console.log(typeof obj4);//object
var obj5 = new Date();
console.log(obj5.constructor);//function Date() { [native code] }
console.log(obj5);//Tue Feb 28 2017 21:13:36 GMT+0800 (中国标准时间) //当前的时间
console.log(typeof obj5);//object

1.3.3 基本数据类型的typeof的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
var func = function(){
console.log("你好");
}
var obj = {"name":"john"};
console.log(typeof 5); //number
console.log(typeof 'name'); //string
console.log(typeof false); //boolean
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof func); // object
console.log(typeof obj); // object
//所有的返回值的类型都会 字符串 类型,注意都是小写字母;但是有一点缺陷就是函数和对象以及DOM对象返回的值都是object,所以typeof用来监测数据类型的时候,如果监测基本数据类型还比较可靠,但是监测对象的时候却无太大作用。
</script>

1.3.5 通过上面分析我们发现typeof可以判断基本数据类型,但是对于复杂数据类型,返回都是object,那么如何检测object的”类”呢?也就是说,如何检测一个对象是由哪个构造函数创建的呢?

这个时候就要用到 instanceof 了;语法: obj instanceof Type ,会沿着对象的原型链一层层的找,如果找到由Type类型的构造函数,则返回true,否则返回false;

1
2
3
4
5
6
7
8
9
function test (){ }
var obj = new test();
console.log(obj.constructor);//function test(){}
console.log(obj);//test{}
console.log(typeof obj);//Object
console.log(obj instanceof test);//true
//表示obj对象是test这个构造函数产生的 obj.__proto__ = test.prototype ;
//obj的原型上__proto__ 指向test.prototype
console.log(obj instanceof Object);//true

1.3.6 或者可以直接调用Object.prototype.toString.call(obj) 来判断obj到底是哪个类型的内置对象

1
2
3
4
5
6
7
8
9
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(1,2)); //[object Number]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call("str"));//[object String]
console.log(Object.prototype.toString.call([1,2,3]));//[object Array]
console.log(Object.prototype.toString.call({name:"Jhon"}));//[object Object]
console.log(Object.prototype.toString.call(new Date()));//[object Date]

2 null undefined 这两个原始数据类型没有属性和方法

2.1 null是一个表示”无”的对象(null 则用于表示尚未存在的对象),转化为数值的时候值为0;典型的用法是:

  • 用来初始化一个变量,该变量将来可能会被赋值成一个对象
  • 用来和一个已经初始化的对象进行比较,这个变量可以是一个对象,也可以不是一个对象
  • 当函数的参数期望是对象时,被用作参数传入
  • 当函数返回值期望是对象时,被当做返回值输出(比如调用API 获取页面元素)
  • 调用API获取页面中的元素,获取不到的时候,返回undefined;
  • 删除事件绑定,事件本身是一个 null ,是一个空的对象,可以添加
  • 作为对象原型链的终点
  • 正则exec()方法如果未找到匹配,则返回值为 null。
  • 字符串 str.match(value) 方法匹配字符串,如果匹配不到,返回null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button" value="按钮"/>
<script>
console.log(document.querySelector("input").onclick);//null
document.querySelector("input").onclick = function(){
console.log("被定义");
};
console.log(document.querySelector("input").onclick);//function(){ console.log("被定义"); }
</script>
</body>
</html>

2.2 undefined 是一个表示”无”的原始值,转化为数值的时候值为0 ;为布尔类型的时候使false ; 典型用法是:

  • 变量被声明了,但是没有赋值,那么该变量的值就是undefined
  • 调用一个函数的时候,如果应该提供的参数没有提供,那么该参数默认是undefined
  • 如果一个对象的属性没有赋值,那么该属性值为undefined
  • 获取某个对象的属性,该对象本身就没有该属性,返回undefined(数组也是对象)
  • 函数没有返回值的时候,默认返回undefined;
  • 函数的实参少于形参个数,未被赋值的形参默认值为undefined
  • 使用shift pop 删除数组中的第一个和最后一个元素的时候,如果数组为空,那么返回值是undefined
1
2
3
4
5
function foo(){
this.age=10;
}
var p1=foo.call(null); //函数执行结果没有返回值,默认返回undefined,
console.log(p1.age);//undefined没有属性和方法,所以会报错

2.3 乱入一个空字符串作为返回值以及NaN作为返回值的情况总结吧

  • str.chatAt(index) 如果index不再0和str.length那么返回一个空字符;
  • 如果期望转化的结果为数字的时候,转化失败的时候,返回NaN

2.4如何区分二者?

  • == 运算符只比较值,不进行类型的比较,比较之前会进行隐式转化,null==undefined 返回true.
  • === 区分两者,不仅仅比较内容,还比较数据类型 null===undefined false

如何判断一个变量是null还是undefined?

  • 如何确定一个变量是undefined;
1
2
3
4
5
6
7
8
9
var exp = undefined ;//var exp ;如果不进行赋值的话,结果也是undefined
//这种方法是错误的,因为null==undefined 返回true;
if(exp == undefined){
console.log("exp变量是undefined");
}
//这种方法才是正确的,注意undefined加"" ,因为typeof返回的值是一个字符串类型的
if(typeof(exp) == 'undefined'){
console.log("exp变量是undefined");
}

以下附上 == 运算符的W3C解释,方便读者回忆基础

1
2
3
4
5
6
7
8
9
10
执行类型转化遵循的规则:
如果一个运算数是 Boolean 值,在检查相等性之前,把它转换成数字值。false 转换成 0,true 为 1。
如果一个运算数是字符串,另一个是数字,在检查相等性之前,要尝试把字符串转换成数字。
如果一个运算数是对象,另一个是字符串,在检查相等性之前,要尝试把对象转换成字符串。
如果一个运算数是对象,另一个是数字,在检查相等性之前,要尝试把对象转换成数字。
还遵循以下转化规则:
值 null 和 undefined 相等。
在检查相等性时,不能把 null 和 undefined 转换成其他值。
如果某个运算数是 NaN,等号将返回 false,非等号将返回 true。
如果两个运算数都是对象,那么比较的是它们的引用值。如果两个运算数指向同一对象,那么等号返回 true,否则两个运算数不等。

我觉得可以进行再简化,来进行解释这个比较过程:

1
2
如果其中一个是布尔类型则先将布尔类型转化 为0 或者 1 ;
如果一个是对象,和字符串、 数字 或者 布尔类型 进行比较的时候则将对象转化为原始值,对象通过toString valueOf 查看原始值,然后在与字符串 数字 布尔类型进行比较
  • 如何确定一个变量是null
1
2
3
4
5
6
7
8
9
10
11
12
var exp = null;
//以下两种是不正确的
if(!exp){ //0 或者undefined同样可以进入if语句
console.log("该变量是null");
}
if(exp == null ){ //undefined == null 返回true
console.log("该变量是null")
}
//下面这种才是正确判断null 类型的
if(typeof(exp) == 'object' && exp == null){ //同时进行类型和内容的判断
console.log("该变量是null");
}

web中的path路径浅析

发表于 2016-11-28 | 分类于 http

之前写过 NodeJs中的path路径浅析 现在简单看下浏览器是如何解析路径的

1 浏览器端解析路径的时候,总是以所解析的文件作为当前页

看下实例demo的目录结构

1
2
3
4
5
6
webPath/
js/
-app.js
-index.html
-ab.html
-abc.html

app.js 以下app文件读取的路径和启动服务器所在目录有着直接的关系,NodeJs中的path路径浅析 已经分析过,不再赘述,这里代码不进行封装了。

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
var http = require('http');
var fs = require('fs');
var template = require('art-template');
var server = http.createServer();
server.listen(8080,function(){
console.log("8080running");
});
server.on('request',function(req,res){
var url = req.url ;
var method = req.method.toLowerCase();
console.log(url);
console.log(method);
if(method === 'get' && url === '/'){
fs.readFile('../index.html','utf-8',function(err,data){
if(err){
throw err ;
}
console.log(data);
var htmlStr = template.compile(data)({info:{flag:'/'}});
res.end(htmlStr)
})
}else if(method === 'get' && url === '/aaa/bbb'){
fs.readFile('../ab.html','utf-8',function(err,data) {
if (err) {
throw err;
}
var htmlStr = template.compile(data)({info: {flag: 'ab'}});
console.log(htmlStr);
res.end(htmlStr)
})
}else if(method === 'get' && url === '/aaa/bbb/ccc'){
fs.readFile('../abc.html','utf-8',function(err,data) {
if (err) {
throw err;
}
var htmlStr = template.compile(data)({info: {flag: 'abc'}});
res.end(htmlStr)
})
}
});

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="../aaa/bbb">地址: ../aaa/bbb</a><br/>
<a href="./aaa/bbb">地址: ./aaa/bbb</a><br/>
<a href="/aaa/bbb">地址: /aaa/bbb</a><br/>
<p>以上三个地址对应的资源是一样的,也就是说上面三种路径的写法在浏览器解析的时候是等价的</p>
<a href="/aaa/bbb/ccc">地址: /aaa/bbb/cc</a><br/>
<a href="/aaa/bbb/./ccc">地址: /aaa/bbb/./ccc</a><br/>
<a href="/aaa/bbb/../bbb">地址: /aaa/bbb/../bbb</a><br/>
<p>flag 标记{{info.flag}}</p>
<p>this is / 对应的内容</p>
</body>
</html>

ab.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="/">back to index</a>
<p>flag 标记 {{info.flag}}</p>
<p>this is /aaa/bbb 对应的内容</p>
</body>
</html>

abc.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="/">back to index</a>
<p>flag 标记 {{info.flag}}</p>
<p>this is /aaa/bbb/ccc对应的内容</p>
</body>
</html>

2 我们发现 ../ ./ 如果放在路径的开头,则会被浏览器“忽略”;在路径内则会按照原来的 ./ 代表当前路径 ../ 代表上级目录进行解析;

其实,从客户端返回的路径对于服务器来说,就是一个“标识符”,还记得标识符吗?当我们学习定义一个变量的时候,要用var name = “Jhon”,其中的name就是标识符,通过name可以直接获取到Jhon,这里的客户端请求的路径对于服务器也是一样的,客户端的请求也就是一个“标识符”,客户端请求一个 / 服务端返回index.html,客户端请求 /aaa/bbb 服务端返回对应的ab.html页面,当然也可以是不同的其他的资源文件。

根本还是根据客户端的标识符,服务器进行响应,然后返回响应的数据,所以我们有可能看到的是‘假路径’,一切都是假的,咯咯。

3 实际情况通过demo的演示会很清楚的显示,大家动手多实践吧。

width 百分比取值基准

发表于 2016-11-22 | 分类于 html

width 百分比取值相对基准问题

一 :标准流下,父元素不定位,不浮动,子元素的100% width相对于哪个元素的width进行取值

二:脱离标准流之后,父元素设置了定位或者浮动之后,子元素的100% width相对于哪个元素的width进行取值

注意理解:

  • 当子元素是标准流的元素的时候,(包括子元素设置position:relative,也是永远相对于父元素的宽高为基准)

    无论父元素是否是标准流 的元素,子元素的width和height的百分比取值永远都是相对于父元素的;

此时无论父元素是否设置定位,子元素的width height padding margin 通过百分数取值的时候,都是相对于其直接父元素。

  • 当子元素不是标准流的时候,比如子元素设置了position:absolute;

    此时子元素的宽高百分比设置的时候,百分比的宽高基准是顺着DOM元素往上寻找最近的一个设置了定位了父元素的宽高为基准,如果祖先元素都没有定位的话,那么就是相对于body的宽高;注意position除了static的父元素 ;

    注意position除了static的父元素 ;

  • 其实绝对定位的子元素的 margin padding 等值的百分比都是相对于顺着DOM节点树向上第一个设置了除了static定位之外的position 的元素的宽度为基准的;

  • % 重点理解:width 是 基于父元素的 width 计算的值
    height 是基于父元素的 height 计算的值
    padding 和 margin 的无论上下左右 值 都是基于DOM树节点祖先元素中第一个设置了除了static定位之外的第一个祖先元素的宽度

    ​

    ​

    ​

    ​

css3 background

发表于 2016-11-22 | 分类于 css3

CSS3 background-origin clip size 背景

1 盒子大小大于背景图的大小,如何避免精灵图周边的其他图片显示出来

一 对于背景色:

  • background-clip : border-box || padding-box || content-box || text

    定义元素的背景图像 从何处开始向外 裁剪,默认值是border-box;

  • bakcground-origin : border-box || padding-box || content-box 该属性改变背景图像 的填充开始原点,对背景色 没有影响

定义元素的背景图像 从何处开始填充,即填充开始的原点;默认值是padding-box ;

注意背景图像必须设置为 no-repeat才会有效果,不然将会完全平铺

  • background-size : auto || length || percentage || cover || container

该属性值设置背景图像的大小,

  • auto是默认值,即背景图像的真实大小,
  • length 可以直接设置背景图像的大小,会将背景图像进行压缩 ,
  • percentage 以百分比设置背景图像的大小,百分比的基准是盛放背景图像的元素的宽高,而不是背景图像本身尺寸的宽高,
  • length和percentage如果只设置一一个值,那么将设置为背景图像的宽度尺寸,第二个值默认auto,根据宽度进行等比缩放;
  • cover 会将背景图像进行等比 缩小或者放大,使其可以完全覆盖容器 ,此时背景图像可能会溢出;
  • container会将背景图像进行等比缩小或者放大到宽度或者高度与容器的宽度或者高度一样,使其可以完全在容器内,此时容器可能会有空余空间;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div{
border: 10px dashed blue;
width: 150px;
height: 150px;
background-color: red;
margin: 50px auto ;
padding: 20px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
1
2
3
4
5
6
7
8
9
给div依次设置以下属性:
background-clip: border-box; //会将背景从border开始向外剪裁
background-clip: padding-box; //会将背景从padding开始向外剪裁
background-clip: content-box; //会将背景从content开始向外剪裁
注意背景默认是填充border边界的,即以border-box为默认值
**对于背景色而言,永远都之直接填充包括border-box为边界内部的区域,background-origin对背景色不起作用;
background-origin:border-box;
background-origin: padding-box;
background-origin: content-box;

将这三个属性依次设置给div ,效果如下:

border-box padding-box

content-box

二 对于背景图像:

1
2
3
4
5
6
7
8
9
10
div{
border: 10px dashed blue;
width: 150px;
height: 150px;
background-color: red;
margin: 50px auto ;
padding: 20px;
background: url("img/01.jpg") no-repeat;
}
1
2
3
4
5
/*background-clip: border-box;*/
/*background-clip: padding-box;*/
/*background-clip: content-box;*/
和背景色一样,都是向外裁剪,但是需要注意,背景图像填充的时候,默认是以padding-box,即padding左上角为原点进行填充整个div的,也就是说,div的上边框和左边框不会被填充,但是下边框和有边框会被填充,如果想要所有的边框被填充,那么需要设置background-origin:border-box ;

三 background属性连写:新版CSS3支持可以写多个背景连写在一起,中间用逗号隔开,最后以分号结尾

1
2
3
4
5
6
7
8
background:
url(img/bg1.png) no-repeat left top,
url(img/bg2.png) no-repeat right top,
url(img/bg4.png) no-repeat left bottom,
url(img/bg3.png) no-repeat right bottom,
url(img/dog.gif) no-repeat center/400px 270px;
background:none [0% 0%] /auto repeat scroll padding-box content-box transparent
background:image pisition size repeat attachment origin clip color
1…678…20
JiM-W

JiM-W

keep fighting!

195 日志
52 分类
90 标签
© 2017 JiM-W
由 Hexo 强力驱动
主题 - NexT.Pisces