/*
* Version 1.0
* Time 2018/3/13
* Author parchments
* Learn for duyijiaoyu
*/
js命名空间
作用: 管理变量, 防止污染全局变量, 适用于模块化开发
1、管理变量
/*
var org = {
part1: {
lin: {
name: "abc",
age: 18
},
jing: {
name: "jingjing",
age: 19
}
},
part2: {
lin2: {
name: "abc",
age: 18
},
jing2: {
name: "jingjing",
age: 19
}
}
}
var parchments = org.part1.linjian,
jing = org.part1.jing;
console.log(jing.name);
console.log(jing['name']);//建议这样访问属性
*/
2、闭包实现私有化,不污染全局变量
/*
var name = 'abcd';
var init = (function(){
var name = 'abc';
function callName(){
console.log(name);
}
return function(){
callName();
}
}());
init();
//结果是打印出abc,因为产生了闭包,函数被保存到了外部执行,拿的是init的AO,也因此没有污染全局的变量name,达到变量私有化的效果,init方法最后返回函数,执行callName();
var initNew = (function(){
var name = 123;
function callName(){
console.log(name);
}
return function(){
callName();
}
}());
initNew();
//结果是打印出123,因为产生了闭包,函数被保存到了外部执行,拿的是init的AO,也因此没有污染全局的变量name,达到变量私有化的效果,init方法最后返回函数,执行callName();
*/
js实现链式调用(模仿jq)
//例如: lin.smoke().drink().smoke().perm();
/*
var lin = {
smoke: function(){
console.log("抽烟了");
return this;
},
drink: function(){
console.log("喝酒了");
return this;
},
perm: function(){
console.log("烫头了");
return this;
}
}
lin.smoke().drink().perm();
//打印出 -->抽烟了 喝酒了 烫头了
*/
js属性表示方法
/*
//obj.prop 内部隐式会转化成 obj['prop']去访问属性,所以用" . "访问属性的时候用obj['prop']的形式会更快
//obj['prop']的形式更快而且更灵活,因为后面可以字符串拼接属性名,例如obj['prop' + num]
//例如:
var lin = {
boke1: {name: "开源博客"},
boke2:{name: "其他博客"},
bokeFn: function(num){
return this['boke' + num];
}
}
//访问lin.bokeFn(1) -->打印出开源博客
//访问lin.bokeFn(2) -->打印出其他博客
*/
js对象枚举
//遍历 枚举 enumeration
1、遍历数组 --> for循环
/*
var arr = [1,2,3,4,5];
for(var i = 0; i<arr.length; i++){
console.log(i);
}
//打印出1 2 3 4 5
*/
2、遍历对象 --> for in 循环
/*
var lin = {
name : 'lin',
age : 18,
//prop : 1
}
for(var prop in lin){
console.log(prop + " " + typeof(prop));
}
//for in
循环能实现对对象的遍历,把对象里面的每个属性名提取出来,有多少个属性名就会循环多少圈,目的只有一个就是遍历对象,单独给对象设立一个循环;通过对象属性的个数来控制循环的圈数,在循环每一圈时,会把对象的属性名放到prop里面。就相当于var
一个prop到lin,在每一圈的时候,prop相当于一个变量,每一圈的时候代替的属性名都不一样。其中prop是可自己设置的,但是lin一定是对象名
//特别注意
//如果要访问对象prop的属性名,一定要用[],否则,如果lin对象里面本来就有prop的属性,那访问的就不是对象的每个属性了,因为用了[prop],prop还是变量而不是定量
for(var prop in lin){
console.log(lin[prop]);//而不是console.log(lin.prop);
}
*/
2、hasOwnProperty过滤原型的属性
/*
//其中如果对象中有原型__proto__,再使用for
in循环的话就会连原型上面的属性也取到,但是一旦原型链延展到Object.prototype上了,它就不会打印了,除非自己设置了Object.prototype
= "XXX",否则是不会打印系统定义的东西
//因此诞生出hasOwnProperty,和for in循环搭配使用,达到过滤原型上的属性,就只打印自己的属性
var lin = {
name : 'lin',
age : 18,
__proto__ : {
lastName : 'linlin'
}
}
for(var prop in lin){
//console.log(prop); //如果只有这一句,没有用hasOwnProperty去限制或者过滤,那么会打印到原型上的属性
if(lin.hasOwnProperty(prop)){ //其中,hasOwnProperty()是一个方法,带参数,就是prop, -->会返回一个布尔值
console.log(prop);
}
}
//因为一般遍历属性都是想要拿自己的属性而不是原型上的属性
*/
3、in操作符
/*
//A、和hasOwnProperty()方法差不多,也是看这个属性到底是不是这个对象的
//例如:
var lin = {
name : 123
}
//作用:判断name是不是lin对象的
//'name' in lin -->会返回一个布尔值,其中name一定要用 双引号''
//因为这样name是一个变量!!!
//in会把是你的属性算是你的属性,也会把原型上的属性也算作是你的属性,所以出现的概率较低
*/
JS正则表达式
补充知识:
1、转义字符“ \ ”,反斜杠,会把反斜杠后面那个东西强制变成,转义符号不会输出,消除转义符号:“ \\ ”,把后面的转义符号转义掉
var str = "ab\"cd"
输出:(2行)
ab
cd
var str = "ab\\cd"
输出:abcd
2、\n,就是换行,在console.log()中查看
var str = "ab\ncd"
window中底层一个回车就是一个"\r\n"
var str = "ab\ncd"
输出:(2行)
ab
cd
3、\t 相当于一个tab键,制表符
var str = "ab\tcd"
4、在编程中让字符串换行
例如1:document.body.innerHTML = "<div><span></span></div>"
会把后面文本的形式的回车转义掉,变成不再是回车
例如2:document.body.innerHTML = "\
<div>\
<span></span>\ </div>\
"
例如3:通过字符串连接的方法,比较low
var text =
" <div>" +
" <span></span>" +
" </div>"
RegExp
正则作用:用户输入后判断字符串里面有没有特定片段、能被什么截取的、符合什么样的格式,甚至修改字符串的功能,正则一行就能处理
正则表达式是一个规则对象,对象里面包含的是规则,所以正则表达式也要创建出来
两个方法:
正则的方法:reg.test();只能判断字符串 有没有符合要求的片段,返回结果只有true或者false
字符串的方法:str.match();(g属性);可以把所有符合的东西匹配返回出来的,比true和false更直观点,还能告诉你多少个
两种创建方式:
1、直接量(推荐)
var reg = //;斜线中间些内容
var reg = /abc/,这代表我要匹配的规则是abc
var str = "abcd" 返回true 包不包含片段,区分大小写
var str = "abce" 返回false
使用方法:控制台:reg.test(str)
加属性(i)忽略大小写,i是ignoreCase的缩写
var reg = /abc/,不忽略大小写
var str = "abC" 返回false
var reg = /abc/i;
var str = "abC" 返回true
加属性(g),全局
var reg = /ab/g
var str = “abababab”
控制台:
str.match(reg);
利用reg的方法test已经不够了,所用str的字符串方法match,把正则表达式传进去就会把符合的片段挑出来;
如果reg后面的没有加属性g
打印的就是["ab"]
如果reg后面的加了属性g,就会把符合要求的片段全部拿出来
打印的就是["ab","ab","ab"]
加属性(m),执行多行匹配-----重要
var reg = /^a/g " ^ "(尖号) 代表字符串开头
var reg1 = /^a/gm " ^ "(尖号) 代表字符串开头
var str = “abcde\na”字符串换行变成多行字符串
在可控制台:
str.match(reg)---->打印出一个a["a"]
str.match(reg1)---->打印出2个a["a","a"]
2、new RegExp()
var str = "abcd";
var reg = new RegExp("abc");
var reg = new RegExp("abc",“i/g/m”);可以加属性
特殊的地方:
var reg = /abcd/i
var reg1 = new RegExp(reg);
现在reg和reg1打印出的值是一样,但他们是不一样的!!!
在控制台打印:
reg
返回:/abcd/i
reg1
返回:/abcd/i
reg.abc = 123;
reg1.abc
返回undefined
reg和reg1打印的样子一样,但是却不一样的。
如果去掉new,那就是一样的人,只是引用不同,2人拿着一个钥匙指向同一个房间。
var reg = /abcd/i
var reg1 = RegExp(reg);
3、正则表达式规则
3.1方括号
1、[ ],一个[ ]代表一位,三个[ ]代表3个值,里面填的东西就是可取值的范围
var str = “1235890asdasd123”
var reg = /123/g
现在要:匹配字符串中有没有是这样的数字,即三个数字相连,要三个数字都是可变的,那现在就是[ ]代表一位。三个[ ]代表3个值
匹配三个数字相连
var reg = /[123456890][123456890][123456890]/g
匹配了就不会往回匹配;
var reg = /[ab][cd][d]/g 匹配第一个为a或者b,第二个为c或者d,第三个是d的全局
var str = “abcd”
在控制台输入str.match(reg)---->返回bcd
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
特殊字符
$ | 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。 |
( ) | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。 |
* | 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。 |
+ | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。 |
. | 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。 |
[ | 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 |
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。 |
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。 |
{ | 标记限定符表达式的开始。要匹配 {,请使用 \{。 |
| | 指明两项之间的一个选择。要匹配 |,请使用 \|。 |
unicode(可以有在线转的)
一个编码对应一个字符,能代表很多语言
表达形式一定加\u;例如: \u0000 十六进制的四位数,简单的Unicode编码,基本能包含汉字
unicode编码包含了一切字符如:\u0000-\uffff
能代表一切的集合的 [\s\S]或者 [\d\D]
.的作用。
量词
\\n+ {1,} 1到正无穷
\\n* {0,} 0到正无穷 0次到多次
var reg = /\w+/g; 这个+意思是前面的这个变量可以出现一次到多次,这个\w可以重复出现无数次。注意这里不是说\w,而是表达后面的+
var str = "abc"
str.match(reg) 返回[“abc”]
var reg = /\w*/g; “*”号
str.match(reg) 返回[“abc”,""]
匹配了一个空串,因为先看abc符不符合要求,然后还有g呢,g的意思是全局匹配,c后面还有一段距离,叫做逻辑上的距离,到c后面没结束,\w*中的*如果变成0的话,匹配的就是空了,然后在这个逻辑点上往后匹配了一个出来。一开始*变成3,后面变成0了,换句话说正则表达式中匹配的就是空
var reg = /\w*/g;var str = "abc";str.match(reg)
(2) ["abc", ""]
var reg = /\d*/g; “*”号 返回4个空
var str = "abc"
str.match(reg) 返回["","","",""]
var reg = /\d*/g;var str = "abc";str.match(reg)
(4) ["", "", "", ""]
返回4个空,逻辑上一开始光标在a的前面匹配出一个空,然后一看a,发现a匹配不了,到了a后面,a后面还是有个空0, 再成0还是一个空,所以有多少个光标定位点就有多少个,所以有4个。上面那个 \w 为什么不是是4个w呢,
一旦\w能识别出值的话,看a能不能识别,b能不能被识别,c能不能被识别,先一连串把能识别的识别掉,到最后的时候才试一下成0,能匹配多久不匹配少的原则,例如现在有一串a
var str = "aaaaaaaaaaaaa"
var reg = /\w+/g;
返回:(2) ["aaaaaaaaaaaaa"]-------------贪婪匹配原则
贪婪匹配,能匹配多就匹配多,能多就不少。能4个就尽量别三个。
n+ {1 ,----正无穷}
n* {0 ,----正无穷}
n? {0, 1}
var reg = /\w?/g;
“n?”号 能取的就是0-1;
var str = "aaa" 返回[“a”,“a”,"a",“”]
最后还有个空格,因为遇到最后没有a了,那就拿个空
n{X} {x}区间个,定死了多少个,
var reg = /\w{3}/g; 三个三个匹配
var str = "aaaaaaaaa"
继承方式(原型是构造函数的祖先,是在构造函数的上面)
1.原型链继承方式
//过多的继承了没有的属性
Grand.prototype.lastName = 'Grand';
function Grand(){
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.name = 'Father'
}
var father = new Father();
Son.prototype = father;
function Son(){
}
var son = new Son();
2.构造函数继承(如果囊括方法直接拽过来用)
//借助被人的方法来用,只能借用构造函数的方法而已。不能继承构造函数的原型,this的原型返回出来还是this.prototype,每次构造出对象都要执行两个方法
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
function Student (name,age,sex,grade){
Person.call(this,name,age,sex);//放this的前提是下面new
this.grade = grade;
}
var student = new Student();//不new的话,上面的call中的this没什么意义
3.共享原型(A继承B)
Father.prototype.name = 'lin';
function Father(){}
function Son(){}
function inherit(target,origin){
target.prototype = origin.prototype;//引用值赋值
}
inherit(Son,Father);
var son = new Son();
4.圣杯模式
A.通常写法
function inherit(target,origin){
function F(){}//
F.prototype = origin.prototype;//F与origin共用原型
target.prototype = new F();//与上面一行不能换顺序,想给Son的原型加东西就不会影响到Father的原型,既能继承又不会被改
target.prototype.constructor = target;//因为target最终继承的是origin的原型,指向了origin的原型,现在要指回到自己的原型
target.prototype.uber = origin.prototype;//源继承自谁
}
Father.prototype.name = 'father';
inherit(Son,Father);
function Father(){}
function Son(){}
var son = new Son();
var father = new Father();
//son.__proto__->new F().__proto__->Father.prototype
B.雅虎写法
var inherit = ( function() {
var F = function (){};
return function(target,origin){
F.prototype = origin.prototype;
target.prototype = new F();
target.prototype.constructor = target;
target.prototype.uber = origin.prototype;
}
}())
Father.prototype.lastName = 'father';
inherit(Son,Father);
function Father(){}
function Son(){}
var son = new Son();
var father = new Father();