├── movie_recommendation ├── app.js ├── page │ ├── images │ │ ├── headImg.jpg │ │ └── icon │ │ │ ├── about.png │ │ │ ├── home.png │ │ │ ├── selectedAbout.png │ │ │ └── selectedHome.png │ ├── about │ │ ├── about.json │ │ ├── about.wxss │ │ ├── about.wxml │ │ └── about.js │ ├── detail │ │ ├── detail.json │ │ ├── detail.wxss │ │ ├── detail.wxml │ │ └── detail.js │ └── index │ │ ├── index.json │ │ ├── index.wxss │ │ ├── index.wxml │ │ └── index.js ├── README.md ├── app.json └── project.config.json ├── .gitattributes ├── README.md ├── js-exercise ├── 008input-array-sum.html ├── 002alert-input-value.html ├── 004mouseover-onmuseout.html ├── 005remember-password.html ├── 003ergodic-change-background.html ├── 007innerHTML.html ├── 006baidu-typewriting.html └── 001control-div.html └── javascriptLearnLog ├── js笔记四十九之正则表达式(5).md ├── js笔记六之基本数据类型和引用数据类型的区别.md ├── js笔记之js库utils.js(持续更新).md ├── js笔记七之函数初步了解.md ├── js笔记三十七之函数的三种角色.md ├── js笔记五之对象(object)类型.md ├── js笔记三之布尔(Boolean),字符串(String),null和undefined.md ├── js笔记二之数据类型.md ├── js笔记四之数字(Number)类型.md ├── js笔记二十三之函数的操作.md ├── js笔记十二之Math数学函数.md ├── js笔记三十八之call方法深入.md ├── js笔记四十六之正则表达式(2).md ├── js笔记九之for,for-in循环.md ├── js笔记二十八之内存释放与作用域销毁.md ├── js笔记三十九之call,apply和bind的区别.md ├── js笔记三十五之原型链模式扩展(2).md ├── js笔记三十一之构造函数模式基础.md ├── js笔记二十五之函数中的return及匿名函数.md ├── js笔记一之初识JS.md ├── js笔记二十七之预解释的特殊处理及上级作用域.md ├── js笔记五十一之js盒子模型.md ├── js笔记十八之Date日期.md ├── js笔记十六之DOM基础-节点.md ├── js笔记三十四之原型链模式扩展(1).md ├── js笔记三十之单例模式和工厂模式.md ├── js笔记四十一类数组转换为数组(浏览器异常捕获).md ├── js笔记四十四之表格排序,DOM映射及初识ajax.md ├── js笔记四十七之正则表达式(3).md ├── js笔记四十二之sort深入研究.md ├── js笔记二十六之预解释.md ├── js笔记四十五之正则表达式(1).md ├── js笔记二十四之函数的形参与实参.md ├── js笔记三十三之原型链模式基础.md ├── js笔记十一之数据类型转换.md ├── js笔记二十之Array数组的查询,拼接,转字符串,排列(序).md ├── js笔记四十八之正则表达式(4).md ├── js笔记八之if-else if-else判断语句,三元运算符,switch case判断语句.md ├── js笔记二十九之this关键字.md ├── js笔记三十二之构造函数模式扩展.md ├── js笔记十五之DOM基础-获取元素的方法.md ├── js笔记四十获取数组中的最大值和最小值(四种方法).md ├── js笔记十九之Array数组的增删改.md ├── js笔记五十之数据类型检测.md ├── js笔记十三之字符串及常用方法.md ├── js笔记十之for循环练习.md ├── js笔记二十二之数组排序算法-冒泡,递归,快速,插入.md ├── js笔记十七之DOM操作-增删改.md ├── js笔记四十三之json操作及DOM回流.md ├── js笔记三十六之原型链模式扩展(3).md ├── js笔记十四之Math和字符串方法应用.md ├── js笔记二十一Array数组检查,遍历,去重.md └── README.md /movie_recommendation/app.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /movie_recommendation/page/images/headImg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uplyw/Learning_records/HEAD/movie_recommendation/page/images/headImg.jpg -------------------------------------------------------------------------------- /movie_recommendation/page/images/icon/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uplyw/Learning_records/HEAD/movie_recommendation/page/images/icon/about.png -------------------------------------------------------------------------------- /movie_recommendation/page/images/icon/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uplyw/Learning_records/HEAD/movie_recommendation/page/images/icon/home.png -------------------------------------------------------------------------------- /movie_recommendation/page/images/icon/selectedAbout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uplyw/Learning_records/HEAD/movie_recommendation/page/images/icon/selectedAbout.png -------------------------------------------------------------------------------- /movie_recommendation/page/images/icon/selectedHome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uplyw/Learning_records/HEAD/movie_recommendation/page/images/icon/selectedHome.png -------------------------------------------------------------------------------- /movie_recommendation/page/about/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarBackgroundColor": "#fff", 3 | "navigationBarTextStyle": "black", 4 | "navigationBarTitleText": "关于" 5 | } -------------------------------------------------------------------------------- /movie_recommendation/page/detail/detail.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "电影详情", 3 | "navigationBarBackgroundColor": "#fff", 4 | "navigationBarTextStyle": "black" 5 | } -------------------------------------------------------------------------------- /movie_recommendation/page/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "电影推荐", 3 | "navigationBarTextStyle": "black", 4 | "navigationBarBackgroundColor": "#fff" 5 | } -------------------------------------------------------------------------------- /movie_recommendation/README.md: -------------------------------------------------------------------------------- 1 | ### 2 | ### 根据 学堂在线 [学做小程序](http://www.xuetangx.com/courses/course-v1:TsinghuaX+2018032801X+2018_T1/about) 中1.1 -- 4.7课程整理 3 | 另外在 **`B站`** 中有相同课程 [【2018】学做小程序- 清华大学](https://www.bilibili.com/video/av22004522) 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learning_records 2 | 学习笔记或教程项目 3 | 4 | 根据自己平时学习时所作的笔记,不定时更新 5 | 6 | 1. 第一个学习笔记 **[每周电影推荐](https://github.com/uplyw/Learning_records/tree/master/movie_recommendation)** 7 | 2. 第二个学习笔记 **[JavaScript学习笔记](https://github.com/uplyw/Learning_records/tree/master/javascriptLearnLog)** 8 |   9 | -------------------------------------------------------------------------------- /js-exercise/008input-array-sum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 输入框中数组求和 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /movie_recommendation/page/detail/detail.wxss: -------------------------------------------------------------------------------- 1 | /* page/detail/detail.wxss */ 2 | .movieBox{ 3 | display: flex; 4 | flex-direction: column; 5 | padding: 30px 20px; 6 | font-size: 28rpx; 7 | text-indent: 56rpx; 8 | text-align: justify; 9 | } 10 | .movieBasic{ 11 | padding-left: 50px; 12 | } 13 | .movieImg{ 14 | width: 50%; 15 | margin: 20px 25%; 16 | } -------------------------------------------------------------------------------- /movie_recommendation/page/about/about.wxss: -------------------------------------------------------------------------------- 1 | /* page/about/about.wxss */ 2 | page{ 3 | height: 100%; 4 | } 5 | .page-body-info{ 6 | display: flex; 7 | flex-direction: column; 8 | justify-content: space-around; 9 | text-align: center; 10 | height: 80vh; 11 | } 12 | .userinfo-avatar{ 13 | width: 250rpx; 14 | height: 250rpx; 15 | border: 2px solid orange; 16 | border-radius: 50%; 17 | margin: 0 auto; 18 | } 19 | .source{ 20 | font-size: 28rpx; 21 | color: #999; 22 | text-align: center; 23 | line-height: 1.8; 24 | } -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十九之正则表达式(5).md: -------------------------------------------------------------------------------- 1 | 正则的捕获: 正则的exec方法/字符串的match方法/字符串的replace方法 2 | 3 | replace: 将原有的字符替换成我们新的字符 4 | 5 | ```javascript 6 | var str = "2018-06-19 23:23:00"; 7 | // 2018年06月19日 23点23分00秒 8 | 9 | // 设定好我们目标时间格式, 把数组中对应的项替换到指定的区域内 10 | var resStr = "{0}年{1}月{2}日 {3}时{4}分{5}秒"; 11 | var ary = ["2018","6","19","23","23","0"]; 12 | 13 | // {0}替换成2015:首先要获取 {0}, 而且还要获取那个 0 ,这个 0 相当于ary数组中的索引, 要把对应的索引 14 | 15 | var reg = /{(\d+)}/g; 16 | resStr = resStr.replace(reg,function(){ 17 | // 每一次都会把正则匹配的内容捕获到: 18 | }) 19 | ``` 20 | -------------------------------------------------------------------------------- /movie_recommendation/page/about/about.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 关于小程序 5 | 7 | 8 | uplyw 9 | 10 | 根据哔哩哔哩 11 | https://www.bilibili.com/video/av22004522 12 | 学习整理 -------------------------------------------------------------------------------- /js-exercise/002alert-input-value.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 弹出input的输入 6 | 7 | 8 | 9 | 10 | 11 | 21 | 22 | -------------------------------------------------------------------------------- /movie_recommendation/page/detail/detail.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 片名:{{movies.title}} 5 | 评分:{{movies.rating.average}} 6 | 国家:{{movies.countries}} 7 | 年份:{{movies.year}} 8 | 9 | 10 | {{movies.summary}} 11 | -------------------------------------------------------------------------------- /js-exercise/004mouseover-onmuseout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 鼠标移入移出改变样式 6 | 13 | 14 | 15 |
16 | 25 | 26 | -------------------------------------------------------------------------------- /movie_recommendation/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "page/index/index", 4 | "page/about/about", 5 | "page/detail/detail" 6 | ], 7 | "tabBar": { 8 | "list": [{ 9 | "pagePath": "page/index/index", 10 | "text": "首页", 11 | "iconPath": "page/images/icon/home.png", 12 | "selectedIconPath": "page/images/icon/selectedHome.png" 13 | },{ 14 | "pagePath": "page/about/about", 15 | "text": "关于", 16 | "iconPath": "page/images/icon/about.png", 17 | "selectedIconPath": "page/images/icon/selectedAbout.png" 18 | }], 19 | "color": "#515151", 20 | "selectedColor": "#ffa500" 21 | } 22 | } -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记六之基本数据类型和引用数据类型的区别.md: -------------------------------------------------------------------------------- 1 | 2 | ### 基本数据类型和引用数据类型的区别 3 | 4 | > js是运行在浏览器中的(内核引擎) 5 | > 浏览器会为js提供赖以生存的环境(提供给js代码执行的环境) -> `全局作用域(window/global)` 6 | 7 | ```javascript 8 | var a = 12; 9 | var b = a; 10 | b = 13; 11 | console.log(a) // -> 12 12 | 13 | var obj1 = {name:'lilei'}; 14 | var obj2 = obj1; 15 | obj2.name = 'hanmeimei'; 16 | console.log(obj1.name); // -> hanmeimei 17 | ``` 18 | 19 | **`基本数据类型是按值操作的`**: 基本数据类型在赋值的时候,是直接的把值赋值给变量即可 20 | 21 | **`引用数据类型是按照空间地址(引用地址)来操作的`**: 22 | var n = {name: "lilei"} 23 | 1. 先创建一个变量n 24 | 2. 浏览器首先会开辟一个新的储存空间(内存空间),目的是把对象中需要存储的内容(键值对)分别存储在这个空间中,为了方便后期找到这个空间,浏览器给空间设定一个地址(16进制的) 25 | 3. 把空间的地址赋值给了变量! 26 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记之js库utils.js(持续更新).md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```javascript 4 | var utils = { 5 | // -> listTOArray: 实现将类数组转换为数组 6 | listToArray: function(likeArray){ 7 | var ary = []; 8 | try { 9 | ary = Array.prototype.slice.call(likeAry); 10 | } catch (e){ 11 | for(var i = 0; i < likeArray.length; i++){ 12 | ary[ary.length] = likeArray[i] 13 | } 14 | } 15 | return ary; 16 | }, 17 | 18 | // -> 把JSON格式的字符串转换为JSON格式的对象 19 | jsonParse: function (str) { 20 | return "JSON" in window ? JSON.parse(str) : eval("(" + str + "+"); 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /movie_recommendation/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "setting": { 4 | "urlCheck": false, 5 | "es6": true, 6 | "postcss": true, 7 | "minified": true, 8 | "newFeature": true 9 | }, 10 | "compileType": "miniprogram", 11 | "libVersion": "1.9.94", 12 | "appid": "", 13 | "projectname": "movie", 14 | "isGameTourist": false, 15 | "condition": { 16 | "search": { 17 | "current": -1, 18 | "list": [] 19 | }, 20 | "conversation": { 21 | "current": -1, 22 | "list": [] 23 | }, 24 | "game": { 25 | "currentL": -1, 26 | "list": [] 27 | }, 28 | "miniprogram": { 29 | "current": -1, 30 | "list": [] 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /js-exercise/005remember-password.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 记住密码提示 6 | 7 | 8 |
9 | 10 | 11 |
12 | 22 | 23 | -------------------------------------------------------------------------------- /movie_recommendation/page/index/index.wxss: -------------------------------------------------------------------------------- 1 | /* page/index/index.wxss */ 2 | page{ 3 | height: 100%; 4 | } 5 | .swiperBox{ 6 | height: 100%; 7 | } 8 | .movieBox{ 9 | height: 100%; 10 | display: flex; 11 | flex-direction: column; 12 | justify-content: space-around; 13 | text-align: center; 14 | margin: 0 10px; 15 | position: relative; 16 | } 17 | .movieImg{ 18 | width: 50%; 19 | margin-left: 25%; 20 | } 21 | .recommend{ 22 | font-weight: 600; 23 | color: orangered 24 | } 25 | .returnTswk{ 26 | position: absolute; 27 | top: 10px; 28 | right: 0; 29 | font-size: 28rpx; 30 | padding: 2rpx 8rpx; 31 | border: 1px solid orange; 32 | border-radius: 5rpx; 33 | color: orange; 34 | } -------------------------------------------------------------------------------- /movie_recommendation/page/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 第{{index + 1}}周:{{item.movieName}} 7 | 8 | “ {{item.movieEvaluate}}” 9 | 强烈推荐 10 | 返回本周 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /js-exercise/003ergodic-change-background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 使用for循环改变div背景颜色 6 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | 29 | 30 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记七之函数初步了解.md: -------------------------------------------------------------------------------- 1 | ### 函数数据类型 2 | 3 | > 函数数据类型也是按照地址来操作的 4 | > 5 | > 函数: 具备一定功能的方法 6 | 7 | ```javascript 8 | // 创建函数: 相当于生产了一台洗衣机 9 | function 函数名(){ 10 | // -> 函数体: 实现某一个功能的具体js代码 11 | } 12 | 13 | // 执行函数: 相当于使用洗衣机洗衣服(如果函数创建了但没有执行,函数没有任何意义) 14 | 函数名() 15 | ``` 16 | ```javascript 17 | function fn(){ 18 | console.log(1+1); 19 | } 20 | fn // 输出函数本身 21 | fn() // 2 把函数执行(把函数体中实现功能的代码执行) 22 | 23 | ``` 24 | > 声明的这个函数名和我们之前声明的变量名没有任何区别(function fn()和var fn冲突) 25 | > 26 | > 空间中存储的是函数体中的代码,但是此时的代码都是字符串中的字符而已 27 | > 28 | > 函数只创建而不执行没有意义:因为空间中存储的都是毫无意义的字符串 29 | > 30 | > fn() 函数执行:把函数体中的代码执行 31 | > 32 | > 浏览器创建一个供函数中代码执行的私有环境 -> 私有作用域 33 | > 34 | > 把创建时候空间中存储的字符串拿来,然后变成真正的js表达式代码,然后执行 35 | 36 | ```javascript 37 | // -> 形参:形式参数,函数的入口 38 | 39 | // -> 当我们创建一个函数想要实现某个功能的时候, 40 | // -> 发现有一些材料并不清楚,只有当函数运行的时候, 41 | // -> 别人传递给我我才知道,此时我们就需要设定入口, 42 | // -> 让用户执行的时候通过入口把值给我们 43 | 44 | 45 | function fn(num1,num2){ 46 | console.log(num1+num2) 47 | } 48 | fn(1,2) // -> 3 49 | fn(2,3) // -> 5 50 | ``` 51 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十七之函数的三种角色.md: -------------------------------------------------------------------------------- 1 | ```javascript 2 | function Fn(){ 3 | this.x = 100; 4 | } 5 | Fn.prototype.getX() = function(){ 6 | console.log(this.x); 7 | } 8 | var f = new Fn; 9 | ``` 10 | > 函数本身也会有一些自己的属性: 11 | > length: 0 形参的个数 12 | > name: "Fn" 函数名 13 | > prototype 类的原型,在原型上定义的方法都是当前Fn这个类实例的公有方法 14 | > __ proto__: 把函数当做一个普通对象,执行Function这个类的原型 15 | 16 | **函数在整个js中是最复杂也是最重要的知识** 17 | 18 | 1. 一个函数存在了多面性: 19 | 1. "`普通函数`": 它本身就是一个普通的函数,执行的时候形成私有的作用域(闭包),形参赋值,预解释,代码执行,执行完成后栈内存销毁/不销毁 20 | 2. "`类`": 它有自己的实例,也有一个叫做prototype属性是自己的原型,它的实例都可以指向自己的原型 21 | 3. "`普通对象`": 和 var obj = {}中的obj一样,就是一个普通对象,它作为对象可以有一些自己的私有属性,也可以通过__ proto__找到Function.prototype 22 | 23 | 三者之间互不冲突,没有任何关系 24 | 25 | ```javascript 26 | function Fn(){ 27 | var num = 500; 28 | this.x = 100; 29 | }; 30 | Fn.prototype.getX() = function(){ 31 | console.log(this.x); 32 | }; 33 | Fn.aaa = 1000; 34 | var f = new Fn; // Fn中的this是f 35 | 36 | f.num // -> undefined 37 | f.aaa // -> undefined 38 | var res = Fn(); // Fn中的this是window 39 | res // undefined 40 | 41 | Fn.aaa // 1000 42 | ``` 43 | -------------------------------------------------------------------------------- /js-exercise/007innerHTML.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 获取innerHTML里的内容 8 | 16 | 17 | 18 |
19 |

111231

20 |

221232

21 |

331233

22 |

441234

23 |

551235

24 |
25 | 36 | 37 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记五之对象(object)类型.md: -------------------------------------------------------------------------------- 1 | ### 对象数据类型 object 2 | 3 | > var obj = {name:"lilei",age: 18} 4 | > 每一个对象都是由零到多组 `属性名(key键):属性值(value值)` 组成的,或者说由多组键值对组成的,每一组键值对中间用逗号分隔 5 | > 6 | > 属性: 描述这个对象特点特征的 7 | > 8 | > 对象的属性名是字符串或者数字格式的,存储的属性值可以是任何数据类型 9 | > 10 | #### 操作属性 11 | **`获取属性`** 12 | > 对象名.属性名 // 忽略了属性名的单双引号 13 | > 对象名['属性名'] 14 | 15 | ```javascript 16 | var obj = {name:"lilei",age:18,0:100} 17 | 18 | // -> 获取某个属性名对应的属性值 19 | obj.name // -> "lilei" 20 | obj['name'] // -> "lilei" 21 | 22 | // -> 如果属性名是数字怎么操作 23 | obj.0 // -> 语法不支持 24 | obj[0] 或 obj['0'] // -> 两种都支持 -> 100 25 | 26 | // -> 如果操作的属性名在对象中不存在,获取的结果是 undefined 27 | obj.sex // -> undefined 28 | ``` 29 | 30 | **`增加/修改`** 31 | 32 | > 一个对象的属性名是不能重复的(唯一性) 33 | > 如果之前存在就是修改属性值的操作 34 | > 如果不存在就是新设置(增加)属性的操作 35 | 36 | ```javascript 37 | var obj = {name:"lilei",age:18} 38 | 39 | // -> 增加/修改 -> 40 | obj.sex = "man"; // 增加了属性名sex,并赋值为man 41 | obj['age'] = 19; // 修改了属性名age,并赋了新值19 42 | ``` 43 | 44 | **`删除属性`** 45 | > 假删除: 让其属性值赋值为null,但是属性还在对象中 46 | 47 | ```javascript 48 | obj.sex = null; 49 | ``` 50 | 51 | > 真删除: 把整个属性在整个对象中暴力移除 52 | 53 | ```javascript 54 | delete obj.sex; 55 | ``` 56 | 57 | `思考题: obj[age]和obj['age']有什么区别?` 58 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三之布尔(Boolean),字符串(String),null和undefined.md: -------------------------------------------------------------------------------- 1 | ### 布尔类型 2 | 3 | **`Boolean()`** 4 | 5 | > 把其他类型的值转换为布尔类型 6 | > 7 | > 只有 `0`,`NaN`,`空字符串`,`null`,`undefined`这五个数据值转换为布尔类型的`false`,其余的都为`true` 8 | 9 | **`!`** 10 | 11 | > !=: 不等于; 12 | > 叹号在js中还有一个作用: `取反`,先把值转换为布尔值,然后再取反; 13 | 14 | **`!!`** 15 | 16 | > 在一个叹号取反的基础上再取反,取两次反相当于没有做操作,但是却已经把其他类型的值转换为布尔类型了,和Boolean是相同的效果 17 | 18 | 19 | ### 字符串 20 | > 在js中用`单引号`和`双引号`包起来的都是字符串 21 | 22 | ```javascript 23 | 12 // -> number 24 | `12` // -> string 25 | `[12,23]` // -> 字符串 26 | ``` 27 | - 字符串常用方法 28 | 29 | > charAt 30 | > charCodeAt 31 | > substr 32 | > substring 33 | > slice 34 | > toUpperCase 35 | > toLowerCase 36 | > indexOf 37 | > lastIndexOf 38 | > split 39 | > replace 40 | > match 41 | > ... 42 | 43 | ### null和undefined 44 | 45 | > null: 空,没有 46 | > undefined: 未定义,没有 47 | > 48 | > "": 空字符串,没有 49 | > 0: 也可以理解为没有 50 | 51 | **`空字符串和null的区别`** 52 | 53 | > 例如: 都是去种树 54 | > 空字符串属于挖了个坑,但是什么都没有种; 55 | > null是连坑都没挖 56 | > 57 | > 空字符串相对于null来说开辟了内存,消耗了那么一丢丢的性能 58 | 59 | **`null和undefined的区别`** 60 | > 都是没挖坑 61 | > null一般都是暂时没有,预期中以后会有的(可能以后也没有达到预期): 在js中null一般都是手动先赋值为null,后期我们再给其赋具体值 62 | > undefined: 完全没在预料之内的 63 | 64 | -------------------------------------------------------------------------------- /movie_recommendation/page/about/about.js: -------------------------------------------------------------------------------- 1 | // page/about/about.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | 9 | }, 10 | 11 | /** 12 | * 生命周期函数--监听页面加载 13 | */ 14 | onLoad: function (options) { 15 | var that = this 16 | _getUserInfo(); 17 | function _getUserInfo() { 18 | wx.getUserInfo({ 19 | success: function (res) { 20 | that.setData({ 21 | userInfo: res.userInfo 22 | }) 23 | that.update() 24 | } 25 | }) 26 | } 27 | }, 28 | 29 | /** 30 | * 生命周期函数--监听页面初次渲染完成 31 | */ 32 | onReady: function () { 33 | 34 | }, 35 | 36 | /** 37 | * 生命周期函数--监听页面显示 38 | */ 39 | onShow: function () { 40 | 41 | }, 42 | 43 | /** 44 | * 生命周期函数--监听页面隐藏 45 | */ 46 | onHide: function () { 47 | 48 | }, 49 | 50 | /** 51 | * 生命周期函数--监听页面卸载 52 | */ 53 | onUnload: function () { 54 | 55 | }, 56 | 57 | /** 58 | * 页面相关事件处理函数--监听用户下拉动作 59 | */ 60 | onPullDownRefresh: function () { 61 | 62 | }, 63 | 64 | /** 65 | * 页面上拉触底事件的处理函数 66 | */ 67 | onReachBottom: function () { 68 | 69 | }, 70 | 71 | /** 72 | * 用户点击右上角分享 73 | */ 74 | onShareAppMessage: function () { 75 | 76 | } 77 | }) -------------------------------------------------------------------------------- /js-exercise/006baidu-typewriting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 百度输入法 9 | 24 | 25 | 26 | 27 | 28 | 33 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二之数据类型.md: -------------------------------------------------------------------------------- 1 | ### js中的数据类型 2 | > - 基本数据类型(值类型) 3 | > + number: 数字 4 | > + string: 字符串 5 | > + boolean: 布尔 6 | > + null: 空对象指针 7 | > + undefined: 未定义 8 | > 9 | > - 引用数据类型 10 | > + object: 对象数据类型 11 | > + {} 普通对象 12 | > + [] 数组 13 | > + /^$/ 正则 14 | > + ... 15 | > + function: 函数数据类型 16 | 17 | ```javascript 18 | number : 12 12.5 0 19 | string : 'hello' "hello", // 单双引号包起来的 20 | Boolean : true false 21 | null 22 | undefined 23 | 24 | {name: "lilei",age:18} 25 | [12,23,34] 26 | /^?(\d|([1-9]\d))/ 27 | ``` 28 | 29 | #### 这么多数据类型js如何检测呢? 30 | 31 | - `typeof`: 检测数据类型的运算符 32 | - `instanceof`: 检测某个实例是否属于这个类 33 | - `constructor`: 获取当前实例的构造器 34 | - `Object.prototype.toString.call`: 获取当前实例的所属类信息 35 | 36 | `typeof` 37 | > 使用typeof检测,返回的结果是一个字符串,字符串中的额内容证明了值是属于什么类型 38 | > 39 | > **[局限性]** 40 | > 1. typeof null不是"null"而是"object": 因为null虽然是单独的数据类型,但是它本来的意思是空对象指针,浏览器使用typeof检测的时候会把它按照对象来检测 41 | > 2. 使用typeof无法具体细分出到底是数组还是正则,因为返回的结果都是'object' 42 | 43 | ```javascript 44 | typeof 12 // -> 'number' 45 | var num = 12; 46 | typeof num; // -> 'number' 47 | 48 | typeof true // -> 'boolean' 49 | typeof 'lilei' // -> 'string' 50 | typeof undefined // -> 'undefined' 51 | typeof null // -> 'object' 52 | 53 | typeof {name:"lilei"} // -> 'object' 54 | typeof [12,23,34] // -> 'object' 55 | typeof /^$/ // -> 'object' 56 | ``` 57 | 58 | ```javascript 59 | console.log(typeof typeof []) // -> 'string ' 60 | ``` 61 | -------------------------------------------------------------------------------- /movie_recommendation/page/detail/detail.js: -------------------------------------------------------------------------------- 1 | // page/detail/detail.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | 9 | }, 10 | 11 | /** 12 | * 生命周期函数--监听页面加载 13 | */ 14 | onLoad: function (options) { 15 | this.setData({ 16 | mid:options.mid 17 | }) 18 | var that = this 19 | wx.request({ 20 | url: 'https://liudongtushuguan.cn/v2/movie/subject/' + that.data.mid, 21 | header:{ 22 | "Content-Type": "json", 23 | }, 24 | success:function(res){ 25 | console.log(res) 26 | that.setData({ 27 | movies:res.data 28 | }) 29 | wx.setNavigationBarTitle({ 30 | title: res.data.title + " " + res.data.rating.average + "分", 31 | }) 32 | wx.hideNavigationBarLoading() 33 | } 34 | }) 35 | wx.showNavigationBarLoading() 36 | }, 37 | 38 | /** 39 | * 生命周期函数--监听页面初次渲染完成 40 | */ 41 | onReady: function () { 42 | 43 | }, 44 | 45 | /** 46 | * 生命周期函数--监听页面显示 47 | */ 48 | onShow: function () { 49 | 50 | }, 51 | 52 | /** 53 | * 生命周期函数--监听页面隐藏 54 | */ 55 | onHide: function () { 56 | 57 | }, 58 | 59 | /** 60 | * 生命周期函数--监听页面卸载 61 | */ 62 | onUnload: function () { 63 | 64 | }, 65 | 66 | /** 67 | * 页面相关事件处理函数--监听用户下拉动作 68 | */ 69 | onPullDownRefresh: function () { 70 | 71 | }, 72 | 73 | /** 74 | * 页面上拉触底事件的处理函数 75 | */ 76 | onReachBottom: function () { 77 | 78 | }, 79 | 80 | /** 81 | * 用户点击右上角分享 82 | */ 83 | onShareAppMessage: function () { 84 | 85 | } 86 | }) -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四之数字(Number)类型.md: -------------------------------------------------------------------------------- 1 | ### number 数字 2 | > 正数: 12,负数: -12,零: 0,小数: 12.5都是数字 3 | > js中多增加了一个number类型的数据: `NaN` 4 | 5 | ```javascript 6 | typeof NaN // -> 'number' 7 | ``` 8 | 9 | **`NaN`** 10 | 11 | > not a number: 不是一个数,但是属于number类型 12 | 13 | ```javascript 14 | NaN == NaN // -> false NaN和任何值都不想等 15 | ``` 16 | 17 | **`isNaN()`** 18 | > 用来检测当前这个值是否是非有效数字,如果不是有效数字检测的结果是true,反之是有效数字则为false 19 | 20 | ```javascript 21 | isNaN(0) // -> false 22 | isNaN(NaN) // -> true 23 | isNaN('12') // -> false 24 | //当我们使用isNaN检测值的时候,检测的值不是number类型的,浏览器会默认的把值先转换为number类型,然后再去检测 25 | 26 | isNaN([]) // -> false 27 | ``` 28 | 29 | **`Number()`** 30 | > 把其他数据类型值转化为number类型的值 31 | 32 | ```javascript 33 | Number('12') // -> 12 34 | Number('12px') // -> NaN 35 | // 在使用Number转换的时候只要字符串中出现任何一个非有效数字字符,最后结果都是NaN 36 | 37 | Number(true) // -> 1 38 | Number(false) // -> 0 39 | 40 | Number(null) // -> 0 41 | Number(undefined) // -> NaN 42 | 43 | Number([]) // -> 0 44 | // 把引用数据类型转换为number,首先需要把引用数据类型转换为字符串(toString方法),再把字符串转换为number即刻 45 | // [] -> "" -> 0 空数组转换为空字符串,空字符串转化为0 46 | 47 | Number([12]) // 12 [12] -> '12' -> 12 48 | Number([12,23]) // NaN [12,23] -> '12,23' -> NaN 49 | ``` 50 | 51 | **`parseInt()`** 52 | > 也是把其他数据类型的值转换为number,和Number方法在处理字符串的时候有所区别 53 | 54 | ```javascript 55 | Number('12px') // -> NaN 56 | parseInt('12px') // -> 12 57 | 58 | parseInt('12px13') // -> 12 59 | // 提取规则: 从左到右依次查找有效数字字符,直到遇见非有效数字字符为止(不管后面是否还有,都不找了),把找到的转换为数字 60 | parseInt('px12') // -> NaN 61 | parseInt('12.5px') // -> 12 62 | ``` 63 | 64 | **`parseFloat`** 65 | > 在parseInt的基础上可以识别小数点 66 | 67 | ```javascript 68 | parseInt('12.5px') // -> 12 69 | parseFloat('12.5px') // -> 12.5 70 | ``` 71 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十三之函数的操作.md: -------------------------------------------------------------------------------- 1 | ### 函数的基本操作 2 | 3 | #### js中的函数 4 | 5 | > 函数是指一段在一起的/可以做某一件事的程序,也叫子程序(OOP的)方法 6 | > 7 | > 函数是实现某一功能的方法 8 | 9 | **创建函数** 10 | 11 | ```javascript 12 | function [函数名](){ 13 | // 函数体 14 | // 实现功能的具体的js代码 15 | } 16 | ``` 17 | 18 | **执行函数** 19 | 20 | ```javascript 21 | 函数名() // 把创建的函数执行 22 | 函数名() // 这个函数可以执行很多次 23 | ... 24 | // 每一次执行都相当于把函数体中实现功能的js代码重新执行了一遍 25 | ``` 26 | 27 | ```javascript 28 | // 创建函数 29 | function sun(){ 30 | console.log(1+1) 31 | } 32 | // 执行函数 33 | sum() // -> 2 34 | sum() // -> 2 35 | sum() // -> 2 36 | ``` 37 | 38 | > 在真实项目中, 我们一般会把实现一个具体功能的代码封装在函数中: 39 | > 1. 如果当前这个功能需要在页面中执行多次, 不封装成为函数,每一次想实现这个功能,都需要重新把代码写一遍,浪费时间;而封装在一个函数中, 以后想实现多次这个功能,我们就没有必要重新写代码了,只要把函数重新执行即可,提高了开发效率; 40 | > 2. 封装在一个函数中, 页面中就基本上很难出现重复一样代码了,减少了页面中代码的冗余度 41 | ,提高了代码的重复利用率`低耦合 高内聚` 42 | > 43 | > 我们把以上的特点统称为 **`函数封装`**(OOP面向对象编程思想,需要我们掌握的就是类的继承,封装,多态) 44 | 45 | --- 46 | 47 | #### 函数的核心操作 48 | 49 | **函数的核心原理** 50 | 51 | > 函数作为js中引用类型中的一种,也是按照引用地址来操作的 52 | 53 | **创建函数** 54 | 55 | > 1. 首先会在当前作用域中声明一个函数名(声明的函数名和使用var声明的变量名是一样的操作,var sum;function sum();这两个名字重复了) 56 | > 2. 浏览器首先会开辟一个新的内存空间(分配一个十六进制地址),把函数体中写好的代码当做普通字符串存储在一个内存空间中(创建一个函数如果不执行,函数没有意义) 57 | > 3. 把内存空间的地址赋值给之前声明的那个函数名 58 | 59 | **函数执行** 60 | 61 | > 目的: 把之前存储的实现具体功能的js代码执行 62 | > 63 | > "形参赋值"(跳过) 64 | > "私有作用域的变量提声"(跳过) 65 | > 函数执行,浏览器首先会为其开辟一个新的`私有作用域`(只能执行函数中之前编写的js代码) 66 | > 把之前创建时候存储的那些js代码字符串拿到私有作用域中,然后把它们变成js代码表达式从上到下执行 67 | > "私有作用域是否销毁的问题"(跳过) 68 | 69 | **闭包** 70 | 71 | > 函数执行会形成一个私有的作用域,让里面的私有变量和外界互不影响(相互不干扰,无眠的无法获取里面的变量值),此时可以理解为私有作用域把私有变量保护起来,把这种保护机制称之为`闭包` 72 | 73 | **栈内存** 74 | 75 | > 作用域(全局作用域/私有作用域): 提供一个供js代码执行的环境 76 | 77 | **堆内存** 78 | 79 | > 所有的引用类型,它们需要存储的内容都在堆内存中(相当于一个仓库,目的是存储信息) 80 | > 对象会把键值对存储进来 81 | > 函数会把代码当做字符串存储进来 82 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十二之Math数学函数.md: -------------------------------------------------------------------------------- 1 | ### Math中的常用方法 2 | 3 | > 数学函数: 虽然它叫函数,但是它是对象数据类型的`typeof Math -> object` 4 | > 5 | > Math对象中给我们提供了很多常用的操作数字的方法 6 | > console.dir(Math) 查看所有方法 7 | 8 | - Math.abs(): 取绝对值 9 | 10 | ```javascript 11 | Math.abs(12) // -> 12 12 | Math.abs(-12) // -> 12 13 | ``` 14 | - Math.ceil(): 向上取整 15 | 16 | ```javascript 17 | Math.ceil(12) // -> 12 18 | Math.ceil(12.1) // -> 13 19 | Math.ceil(12.9) // -> 13 20 | Math.ceil(-12.1) // -> -12 21 | Math.ceil(-12.9) // -> -12 22 | ``` 23 | - Math.floor(): 向下取整 24 | 25 | ```javascript 26 | Math.floor(12) // -> 12 27 | Math.floor(12.1) // -> 12 28 | Math.floor(12.9) // -> 12 29 | Math.floor(-12.1) // -> -13 30 | Math.floor(-12.9) // -> -13 31 | ``` 32 | - Math.round(): 四舍五入 33 | 34 | ```javascript 35 | Math.round(12.3) // -> 12 36 | Math.round(12.5) // -> 13 37 | 38 | Math.round(-12.3) // -> -12 39 | Math.round(-12.5) // -> -12 40 | Math.round(-12.51) // -> -13 41 | ``` 42 | - Math.random(): 获取[0-1)之间的随机小数 43 | 44 | ```javascript 45 | for(var i=0;i<100;i++){ 46 | console.log(Math.random()) // 随机输出100个0-1之间的小数 47 | } 48 | // -> 获取[0,10]之间的随机整数 49 | Math.round(Math.random() * 10) 50 | 51 | // -> 获取[3,15]之间的随机整数 52 | Math.round(Math.random()*12+3) 53 | 54 | // -> 获取[n,m]之间的随机整数 55 | Math.round(Math.random()*(m-n) + n) 56 | 57 | ``` 58 | - Math.max(): 获取一组值中的最大值 59 | 60 | ```javascript 61 | Math.max(12,2,34,1,4,6) // -> 34 62 | ``` 63 | - Math.min(): 获取一组值中的最小值 64 | 65 | ```javascript 66 | Math.min(12,2,34,1,4,6) // -> 1 67 | ``` 68 | 69 | - Math.PI: 获取圆周率(π) 70 | 71 | ```javascript 72 | Math.PI // -> 3.141592653589793 73 | ``` 74 | 75 | - Math.pow(): 获取一个值的多少次幂 76 | 77 | ```javascript 78 | Math.pow(10,3) // -> 1000 79 | ``` 80 | 81 | - Math.sqrt(): 开平方 82 | 83 | ```javascript 84 | Math.sqrt(100) 85 | ``` 86 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十八之call方法深入.md: -------------------------------------------------------------------------------- 1 | ```javascript 2 | // Array.prototype.slice -> function(){} 3 | var ary = [12,23,34]; 4 | ary.slice() 5 | // ary.slice -> ary这个实例通过原型链的查找机制找到Array.prototype上的slice方法 6 | // ary.slice() -> 让找到的slice方法执行,在执行slice方法的过程中,才把ary数组进行了截取 7 | ``` 8 | 9 | > call改变this关键字 10 | 11 | ```javascript 12 | // Function.prototype.call = function(){}; 13 | 14 | var obj = {name:"lilei"}; 15 | function fn(){ 16 | console.log(this); 17 | } 18 | fn(); // -> window 19 | obj.fn(); // -> Uncaught TypeError: obj.fn is not a function 20 | fn.call(obj) // -> {name: "lilei"} 21 | ``` 22 | > call方法的作用: 23 | > 首先我们让原型上的call方法执行,在执行call方法的时候,我们放fn方法中的this变为第一个参数值obj,然后再把fn这个函数执行; 24 | 25 | ```javascript 26 | // 重写call方法 27 | Function.prototype.myCall = function (context){ 28 | // -> myCall方法中的this就是当前要操作和改变其this关键字的那个函数名 29 | 30 | // -> 1. 让fn中的this关键字变为context的值 -> obj 31 | // -> 让this这个函数中的"this关键字"变为context 32 | 33 | // this.toString().replace("this","obj") 34 | 35 | // -> 2. 让fn方法在执行 36 | // this() 37 | }; 38 | fn.myCall(obj); // -> myCall方法中的this是fn 39 | sum.myCall(obj) // -> myCall方法中的this是sum 40 | function sum(){ 41 | 42 | }; 43 | ``` 44 | 45 | ```javascript 46 | function fn1(){console.log(1);} 47 | function fn2(){console.log(2);} 48 | fn1.call(fn2) // -> 1 49 | // -> 首先fn1通过原型链机制找到 Function.prototype上的call方法,并且让call方法执行 50 | // -> 此时call这个方法中的this就是我们要操作的fn1 51 | // -> 在call方法代码执行的过程中首先让 fn1 中的"this关键字"变成 fn2 ,然后在让 fn1 这个方法执行 52 | 53 | fn1.call.call(fn2) // -> 2 54 | // -> fn1.call 首先fn1通过原型链找到Function.prototype上的call方法 55 | // -> 然后在让call方法通过原型在找到Function原型上的call 56 | // -> (因为call本身的值也是一个函数,所以同样可以找到Function.prototype) 57 | // -> 在第二次再找到call的时候让方法执行,方法中的this是 fn1.call 58 | // -> 首先让这个方法中的this变为fn2,然后再让fn1.call执行 59 | 60 | fn1.call.call.call.call.call(fn2) // -> 2 61 | 62 | Function.prototype.call(fn1); // 什么都不输出 63 | 64 | Function.prototype.call.call.call(fn1); // -> 1 65 | ``` 66 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十六之正则表达式(2).md: -------------------------------------------------------------------------------- 1 | 在正则中字面量创建方式和实例创建方式是有区别的 2 | 3 | 1. 在字面量方式中, ` // ` 之前包起来的所有内容都是元字符,有的具有特殊意义,大部分都是代表本身含义的普通元字符 4 | 5 | ```javascript 6 | var name = "lilei"; 7 | var reg = /^\d+"+name+"\d+$/ 8 | console.log(reg.test("2017lilei2018")); // -> false 9 | console.log(reg.test('2017""nameee"2018')); // -> true 10 | ``` 11 | > 对于这样的需求,我们只能使用实例创建的方式 12 | 13 | ```javascript 14 | var name = "lilei"; 15 | var reg = new RegExp("^\\d+" + name + "\\d+$", "g"); 16 | console.log(reg.test("2017lilei2018")); // -> true 17 | ``` 18 | 19 | ##### 元字符应用 20 | 21 | **规律** 22 | 1. `[]` 在中括号中出现的所有字符都是代表本身意思的字符(没有特殊的含义) 23 | 2. `[]` 中括号中不识别两位数 24 | 25 | - 有效数字正则 -> 正数/负数/零/小数 26 | 27 | > 1. `.`可以出现也可以不出现,但是一旦出现,后面必须跟着一位或者多位数字 28 | > 2. 最开始可以有 `+/-` 也可以没有 29 | > 3. 整数部分,一位数可以是0-9之间的一个,多位数不能以0开头 30 | 31 | ```javascript 32 | var reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/ 33 | ``` 34 | ```javascript 35 | var reg1 = /^[12]$/; // -> 1或者2 36 | var reg2 = /^[12-68]$/ // -> 1/2-6/8三个中的一个 37 | var reg3 = /^[\w-]$/ // ->数字,字母,下划线,- 中的一个 38 | ``` 39 | 40 | - **区别** 41 | 42 | a. 字面量方式中出现的一切都是元字符,所以不能进行变量值的拼接,而实例创建方式是可以的 43 | 44 | b. 字面量方式中直接写 ` \d ` 就可以,而在实例中需要把它转义 ` \\d ` 45 | 46 | - **实例** 47 | 48 | 1. 年龄介于18-65之间 49 | 50 | ```javascript 51 | var reg = /^(1[8-9]|[2-5]\d|6[0-5])$/ 52 | console.log(reg.test(16)) // -> false 53 | console.log(reg.test(18)) // -> true 54 | console.log(reg.test(25)) // -> true 55 | console.log(reg.test(47)) // -> true 56 | console.log(reg.test(65)) // -> true 57 | console.log(reg.test(88)) // -> false 58 | ``` 59 | 60 | 2. 验证邮箱的正则(简版) 61 | 62 | `@` 左边:数字,字母,下划线, ` . ` , ` - ` 63 | 64 | ```javascript 65 | var reg = /^[\w.-]+@[0-9a-zA-Z]+(\.a-zA-Z)[2,4]{1,2}$/ 66 | ``` 67 | 68 | 3. 中国标准真实姓名 2-4 位汉字 69 | 70 | ```javascript 71 | var reg = /^[\u4e00-\u9fa5]{2,4}$/ 72 | ``` 73 | 74 | 4. 身份证号码 75 | 76 | ```javascript 77 | // 简版 78 | var reg = /^\d{17}(\d|X)$/; 79 | // 进阶版 80 | var reg = /^\d{2}\d{4}\d{4}\d{2}\d{2}\d{2}\d(\d|X)$/ 81 | ``` 82 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记九之for,for-in循环.md: -------------------------------------------------------------------------------- 1 | ### 循环操作语句 2 | > 循环: 重复做一件事情 3 | 4 | **`for循环`** 5 | ```javascript 6 | // for(设置循环起始值;设置循环执行的条件;步长累加){ 7 | // 循环体: 重复做的事情都在循环体中 8 | // } 9 | 10 | for(var i=0;i<5;i++){ 11 | console.log(i) // 0 1 2 3 4 12 | } 13 | console.log(i) // 5 14 | ``` 15 | 16 | ```javascript 17 | var i=0 18 | for(;i<5;){ // 初始值可以在循环外声明,但不能省略分号, 19 | console.log(i) // 省略步长会陷入死循环,导致浏览器崩溃 20 | i++; // 步长累加可以放在循环体中 21 | } 22 | console.log(i) 23 | ``` 24 | 25 | ```javascript 26 | for(var i = 0;i < 5;i++){ 27 | console.log(i); 28 | continue; 29 | // 结束本轮循环,继续执行下一轮: 循环体中continue后面的代码都不会再执行,它会直接的去执行步长,然后进入到下一轮 30 | // ... 31 | } 32 | console.log(i); // -> 5 33 | ``` 34 | 35 | ```javascript 36 | for(var i = 0;i < 5;i++){ 37 | console.log(i); 38 | break; 39 | // 结束整个循环: 循环体中一旦遇到break,首先后面代码不执行了,而且步长累加也不执行了,循环都结束了 40 | // ... 41 | } 42 | console.log(i); // -> 0 43 | ``` 44 | *面试题* 45 | ```javascript 46 | for(var i=1;i<10;i+=2){ 47 | if(i<5){ 48 | i++; 49 | continue; 50 | }else{ 51 | i+=3; 52 | break; 53 | } 54 | console.log(i) 55 | } 56 | console.log(i) // -> 10 57 | ``` 58 | 59 | ### for - in循环 60 | 61 | ##### 用来遍历(循环)对象键值对的 62 | 63 | 64 | > 对象中有多少组键值对,我们的for in循环就遍历多少次(不一定) 65 | > 每一次循环key这个变量存储的都是当前循环这组键值对的属性名 66 | > - key存储的值都是字符串格式的(不管属性名是不是数字) 67 | > - 在for in循环遍历的时候,大部分浏览器都是先把对象中的键值对进行排序(把数字属性名的排在前面,并且排列的时候按照数字有小到大排列`[小数不算]`),其次再把非数字的属性名按照之前编写的顺序排列,循环的时候按照重新排列的顺序依次遍历 68 | 69 | ```javascript 70 | var obj = {name:"lilei",age:18,1:"abc",3:"ABC",2:"xyz"} 71 | // -> 对象中有多少组键值对,我们的for in循环就遍历多少次(不一定) 72 | // -> 每一次循环key这个变量存储的都是当前循环这组键值对的属性名 73 | for(var key in obj){ 74 | console.log(key) // -"string" 1,2,3,name,age 75 | console.log(obj.key) // undefined 76 | console.log(obj[key]) //每一次循环把key存储的值(当前遍历的属性名)获取到放在中括号中,获取obj中对应的属性的属性值 77 | } 78 | // 'key': 字符串key,属性名 79 | // key: 变量key,代表的是存储的值 80 | 81 | // obj['key'] obj.key: 属性名是key 82 | // obj[key]: 属性名不是key而是key变量存储的值 83 | ``` 84 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十八之内存释放与作用域销毁.md: -------------------------------------------------------------------------------- 1 | #### 堆内存 2 | 3 | > 对象数据类型或者函数数据类型在定义的时候首相都会开辟一个堆内存 4 | > 堆内存有一个引用地址,如果外面有变量等知道了这个地址,那么这个地址就是被占用了,就不能被销毁了 5 | 6 | ```javascript 7 | var obj1 = {name:"lilei"}; 8 | var obj2 = obj2; 9 | 10 | // null: 空对象指针 11 | // 我们想要让堆内存释放/销毁,只需要把所有引用它的变量赋值为null即可, 12 | // 如果当前的堆内存没有任何东西被占用,那么浏览器会在空闲的时候把它销毁 13 | obj1 = null; 14 | obj2 = null; 15 | ``` 16 | 17 | #### 栈内存 18 | 19 | > 1. 全局作用域 20 | > 只有当页面关闭的时候全局作用域才会销毁 21 | > 22 | > 2. 私有作用域(只有函数执行会产生私有作用域) 23 | > 一般情况下,函数执行会形成一个新的私有作用域,当私有作用域中的代码执行完成后,当前作用域都会主动的释放和销毁 24 | > **特殊情况**: 25 | > 当前私有作用域中的部分内存被作用域外的东西占用了,那么当前的这个作用域就不能销毁了 26 | 27 | ```javascript 28 | // 函数执行返回了一个引用数据类型的值, 并且在函数的外面被一个其他的东西给接收了, 29 | // 这种情况下一般形成的私有作用域都不会被销毁 30 | function fn(){ 31 | var num = 100; 32 | return function (){ 33 | 34 | } 35 | } 36 | var f = fn(); // fn执行形成的这个私有作用域就不能再销毁了 37 | ``` 38 | ```html 39 | 40 |
41 | 49 | ``` 50 | ```javascript 51 | // 下述情况属于不立即销毁 -> fn返回的函数没有别其他的东西占用, 但是还需要执行一次呢 52 | // 所以暂时不销毁, 当返回的值执行完成后, 浏览器会在空闲的时候把它销毁了 53 | function fn(){ 54 | var num = 100; 55 | return function () { 56 | 57 | } 58 | }; 59 | fn()(); // 首先执行fn, 返回一个小函数对应的内存地址, 然后紧接着让返回的小函数再执行 60 | ``` 61 | ++ i 和 i ++ 62 | 都是自身累加1, 在和其他的值进行运算的时候有区别的 63 | i ++ :先拿i的值进行运算, 运算完成本身再+1 64 | ++ i :先本身累加1 ,然后拿累加完成的结果去运算 65 | 66 | #### 作用域练习题 67 | 68 | ```javascript 69 | function fn(){ 70 | var i = 10; 71 | return function(n){ 72 | console.log(n + (++i)); 73 | } 74 | } 75 | var f = fn(); 76 | f(10); // 21 77 | f(20); // 32 78 | fn()(10); // 21 79 | fn()(20); // 31 80 | ``` 81 | ```javascript 82 | function fn(i){ 83 | return function(n){ 84 | console.log(n + i++); 85 | } 86 | } 87 | var f = fn(13); 88 | fn(12); // 25 89 | fn(14); // 28 90 | fn(15)(12); // 27 91 | fn(16)(13); // 29 92 | ``` 93 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十九之call,apply和bind的区别.md: -------------------------------------------------------------------------------- 1 | #### call 2 | ```javascript 3 | var obj = {name:"lilei"}; 4 | function fn(num1,num2){ 5 | console.log(num1+num2); 6 | console.log(this); 7 | } 8 | fn(100,200); // -> 300 window -> num1=100,num2=200 this - window 9 | fn.call(100,200); // -> NaN Number {100} -> num1=200,num2=undefined this - 100 10 | fn.call(obj,100,200); // -> NaN Number {100} -> num1=100,num2=200 this - obj 11 | 12 | // fn.call传的值,第一个参数是给fn的this关键字的,后面的参数是给fn传的参数 13 | 14 | fn.call(); // -> this - window 15 | fn.call(null); // -> this - window 16 | fn.call(undefined); // -> this - window 17 | 18 | ``` 19 | ```javascript 20 | // 严格模式 21 | "use strict"; // -> 告诉当前浏览器接下来的js代码将按照严格模式进行编写 22 | var obj = {name:"lilei"}; 23 | function fn(num1,num2){ 24 | console.log(num1+num2); 25 | console.log(this); 26 | }; 27 | 28 | fn.call(); // -> this - undefined 29 | fn.call(null); // -> this - null 30 | fn.call(undefined); // -> this - undefined 31 | ``` 32 | #### apply 33 | 34 | > apply和call的方法的作用是一模一样的,都是用来改变方法的this关键字并且把方法执行; 35 | > 而且在严格模式下和非严格模式下对于第一个参数是null和undefined这种情况的规律也是一样的; 36 | 37 | ```javascript 38 | var obj = {name:"lilei"}; 39 | function fn(num1,num2){ 40 | console.log(num1+num2); 41 | console.log(this); 42 | }; 43 | 44 | // fn.call(obj,100,200); 45 | fn.apply(obj,[100,200]); 46 | ``` 47 | > call在给fn传递参数的时候,是一个个的传递值的,而apply不是一个个传 48 | > 而是把要给fn传递的参数值统一的放在一个数组中进行操作 49 | > 但是也相当于一个个的给fn的形参赋值 50 | 51 | #### bind 52 | > ie6~8不兼容 53 | > 和call/apply类似都是用来改变this关键字的 54 | 55 | ```javascript 56 | var obj = {name:"lilei"}; 57 | function fn(num1,num2){ 58 | console.log(num1+num2); 59 | console.log(this); 60 | }; 61 | 62 | // fn.call(obj,100,200); 63 | fn.bind(obj,100,200); 64 | ``` 65 | > `call`: 改变this和执行fn函数是一起完成了 66 | > `bind`: 只是改变了fn中的this为obj,并且给fn传递两个参数值1,2;但是此时并没有把fn这个函数执行; 67 | > 执行bind会有一个返回值,这个返回值tempFn就是我们把fn的this改变后的那个结果 68 | 69 | ```javascript 70 | var obj = {name:"lilei"}; 71 | function fn(num1,num2){ 72 | console.log(num1+num2); 73 | console.log(this); 74 | }; 75 | var tempFn = fn.bind(obj,100,200); 76 | tempFn(); 77 | ``` 78 | - bind中的预处理思想: 79 | 预处理: 事先把fn的this改变为我们想要的结果,并且把对应的参数值也准备好,以后要用到了,直接执行即可 80 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十五之原型链模式扩展(2).md: -------------------------------------------------------------------------------- 1 | 在原型模式中,this常用的有两种情况: 2 | 1. 在类中 this.xxx=xxx; this -> 当前类的实例 3 | 2. 某一个方法中的this -> 看执行的时候 `.` 前面是谁this就是谁 4 | 1. 需要先确定this的指向(this是谁); 5 | 2. 把this替换成对应的代码 6 | 3. 按照原型链查找机制, 一步步的查找结果 7 | 8 | ```javascript 9 | function Fn(){ 10 | this.x = 100; 11 | this.y = 200; 12 | } 13 | Fn.prototype = { 14 | constructor: Fn, 15 | y: 300, 16 | getX: function(){ 17 | console.log(this.x) 18 | }, 19 | getY: function(){ 20 | console.log(this.y) 21 | } 22 | } 23 | var f = new Fn; 24 | f.getX() // -> 100 => console.log(f.x) => 100 25 | f.__proto__.getX() // -> undefined => this是f.__proto__ => console.log(f.__proto__.x)[忽略私有,直接找原型] => undefined 26 | Fn.prototype.getX(); // -> undefined 27 | f.getY(); // -> 200 28 | f.__proto__getY() // -> 300 29 | ``` 30 | ```javascript 31 | // 在内置类的原型上扩展数组去重方法 32 | Array.prototype.myUnique = function(){ 33 | // this -> 34 | var obj = {}; 35 | for(var i=0;i this -> Array.prototype 52 | ``` 53 | 54 | > 链式写法: 执行完成数组的一个方法可以紧接着执行下一个方法 55 | > ary为什么可以使用sort方法? -> 因为sort是Array.prototype上的公有的方法,而数组ary是Array这个类的一个实例,所以ary可以使用sort方法 -> 数组才能使用Array原型上定义的属性和方法 56 | > sort执行完成的返回值是一个排序后的数组,可以继续执行reverse 57 | > reverse执行完成的返回值是一个数组,可以继续执行pop 58 | > pop执行完成的返回值是一个被删除的那个元素 59 | 60 | ```javascript 61 | ary.sort(function(a,b){ 62 | return a-b; 63 | }).reverse().pop(); 64 | ``` 65 | 66 | 思考练习: 67 | 68 | 在数组的原则上有一个方法叫做slice, 自己实现一个方法mySlice, 要求和原来的slice功能一模一样 69 | 70 | ```javascript 71 | Array.prototype.mySlice = function(){ 72 | // js code... 73 | } 74 | ``` 75 | > 考虑情况: 76 | > slice(n,m) 77 | > slice(n) 78 | > slice() 79 | > n和m是负数 80 | > n n和m的值超过数组的长度 82 | > n和m不是有效数字 83 | > ... 84 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十一之构造函数模式基础.md: -------------------------------------------------------------------------------- 1 | 2 | #### 构造函数基础 3 | 4 | ```javascript 5 | // 工厂模式 6 | function createJsPerson(name,age){ 7 | var obj = {} 8 | obj.name = name; 9 | obj.age = age; 10 | obj.writeJs = function(){ 11 | console.log("my name is " + this.name + ",I can write js!") 12 | } 13 | return obj; 14 | } 15 | var p1 = createJsPerson("lilei",18); 16 | p1.writeJs(); 17 | ``` 18 | 19 | > 构造函数模式的目的就是为了创建一个自定义类, 并且创建这个类的实例 20 | > 21 | > 构造函数模式和工厂模式的区别: 22 | > 1. 执行的时候: 23 | > 普通函数执行 -> createJsPerson() 24 | > 构造函数执行 -> new createJsPerson() 通过new执行后, createJsPerson就是一个类了 25 | > 而函数执行的返回值(p1)就是CreateJsPerson这个类的一个实例 26 | > 2. 在函数代码执行的时候: 27 | > 相同: 都是形成一个私有的作用域, 然后形参赋值 -> 预解释 -> 代码从上到下执行(类和普通函数一项, 它也有普通函数的一面) 28 | > 不同: 在代码执行之前, 不用再手动创建obj对象了, 浏览器会默认的创建一个对象数据类型的值(这个对象其实就是当前类的一个实例); 29 | > 接下来代码从上到下执行, 以当前的实例为执行的主体(this代表的就是当前的实例), 然后分别的把属性名和属性值赋值给当前的实例 30 | > 浏览器会默认的实例返回 31 | 32 | ```javascript 33 | function CreateJsPerson(name,age){ 34 | // 浏览器默认创建的对象就是实例 p1 35 | this.name = name; // -> p1.name = name 36 | this.age = age; // -> p1.age = age 37 | this.writeJs = function(){ 38 | console.log("my name is " + this.name + ",I can write js!") 39 | } 40 | // 浏览器会把创建的实例默认的进行返回 41 | } 42 | // 因为内置类首字母大写,所以我们约定自己创建的类首字母也大写 43 | var p1 = new CreateJsPerson("lilei",18); 44 | p1.writeJs(); 45 | var p2 = new CreateJsPerson("hanmeimei",16); 46 | p2.writeJs(); 47 | 48 | res = CreateJsPerson("liyanwei",26); 49 | // 这样写不是构造函数模式执行,而是普通的函数执行, 由于没有写return, 所以 res=undefined 并且CreateJsPerson这个办法中的this是window 50 | console.log(res) // undefined 51 | ``` 52 | 53 | > 创建一个数组 54 | 55 | ```javascript 56 | var ary = []; // 字面量方式 57 | var ary = new Array(); // 实例创建的方式 -> 构造函数模式执行的方式 58 | 59 | // 不管哪种方式,ary都是Array这个类的一个实例 60 | ``` 61 | 62 | > js中所有的类都是函数数据类型的, 它通过new执行变成了一个类, 但是它本身也是一个普通的函数 63 | > js中所有的实例都是对象数据类型的 64 | 65 | > 在构造函数模式中,类中(函数体中)出现的 this . xxx = xxx中的this是当前类的一个实例 66 | 67 | > p1和p2都是CreateJSPerson这个类的实例, 所以都拥有writeJS这个方法, 但是不同实例之间的方法是不一样的 68 | > 在类中给实例增加的属性( this.xxx = xxx)属于当前实例的私有的属性, 实例和实例之间是单独的个体, 所以私有的属性之间是不相等的 69 | 70 | ```javascript 71 | console.log(p1.writeJs === p2.writeJs); // -> false 72 | ``` 73 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十五之函数中的return及匿名函数.md: -------------------------------------------------------------------------------- 1 | ### js中的返回值 `return` 2 | 3 | ```javascript 4 | function sum(){ 5 | var total = null; 6 | for (var i = 0; i < arguments.length; i++) { 7 | var cur = Number(arguments[i]); 8 | !isNaN(cur)?total += cur:null; 9 | } 10 | } 11 | sum(10,20); 12 | console.log(total) //Uncaught ReferenceError: total is not defined 闭包的保护机制导致私有作用域会保护里面的私有变量 13 | ``` 14 | 15 | > 返回值是一个函数提供的一个出口: 我们如果想在外面使用函数私有的一些信息,,那么就需要通过return,把这些信息返回出来 16 | 17 | ```javascript 18 | function sum(){ 19 | var total = null; 20 | for (var i = 0; i < arguments.length; i++) { 21 | var cur = Number(arguments[i]); 22 | !isNaN(cur)?total += cur:null; 23 | } 24 | return total; 25 | // return后面跟着的都是值(返回的都是值): 此处不是把total变量返回,而是把total存储的值返回 26 | } 27 | console.log(sum(10,20)); // -> 30 28 | // sum: 函数本身 29 | // sum(): 让函数先执行,代表的是当前函数返回的结果 30 | ``` 31 | 32 | ```javascript 33 | function sum(){ 34 | var total = 0; 35 | // return; 36 | } 37 | console.log(sum()) // -> undefined 38 | // 如果函数中没有return或者return后面啥也没有,默认返回的结果也是undefined 39 | ``` 40 | 41 | ```javascript 42 | function sum(){ 43 | var total = 0; 44 | return; 45 | console.log(total) // 在函数体中遇到return后,return后面的代码都不再执行 46 | } 47 | console.log(sum()) 48 | ``` 49 | ```javascript 50 | function sum(){ 51 | var total = null; 52 | for (var i = 0; i < arguments.length; i++) { 53 | var cur = Number(arguments[i]); 54 | !isNaN(cur) ? total += cur : null; 55 | } 56 | return total; 57 | } 58 | var total = sum(10,20,30); // 外面是全局下的total 和 函数中的total没有必然联系 59 | console.log(total) 60 | ``` 61 | 62 | ### 匿名函数 63 | 64 | > 没有名字的函数 65 | > 函数表达式 66 | > 自执行函数 67 | 68 | - 函数表达式 69 | 70 | ```javascript 71 | oBox.onclick = function(){ 72 | // 把一个没有名字的函数(有名字也无所谓)作为值赋值给一个变量或者一个元素的某个时间等: 函数表达式 73 | } 74 | ``` 75 | 76 | - 自执行函数 77 | 78 | ```javascript 79 | (function(n){ 80 | // 创建函数和执行函数放在一起了,创建完成立马执行: 自执行函数 81 | })(10) 82 | 83 | // 自执行函数 1 84 | ~function(n){ 85 | 86 | }(10); 87 | 88 | // 自执行函数 2 89 | -function(n){ 90 | 91 | }(10); 92 | 93 | // 自执行函数 3 94 | +function(n){ 95 | 96 | }(10); 97 | 98 | // 自执行函数 4 99 | !function(n){ 100 | 101 | }(10) 102 | ``` 103 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记一之初识JS.md: -------------------------------------------------------------------------------- 1 | ### 浏览器(Browser) 2 | #### 内核 3 | 1. `webkit内核 [v8引擎]`: (google chrome/safari/opera/大部分国产浏览器) 4 | 2. `gecko内核`: (Mozilla Firefix) 5 | 3. `Trident排版引擎`: (Internet Explorer) 6 | 4. `Presto内核`: 7 | 5. `KHTML排版引擎`: 8 | 9 | ### W3C 万维网联盟 10 | `制定编程语言的规范与标准` 11 | 开发者按照规范编写代码,浏览器开发商也会开发一套按照规范把代码渲染成页面的东西(这个东西就是内核或引擎) 12 | 13 | 14 | ### JS的三种引入方式 15 | ```html 16 | 17 | 18 |
点击
19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | ``` 29 | 30 | ### JavaScript 31 | 32 | > ECMAScript(ES): 规定了js的一些基础核心的知识(变量/数据类型/语法规范/操作语句等) 33 | > 34 | > DOM: document object model 文档对象模型,里面提供了一些属性和方法,可以让我们操作页面中的元素 35 | > 36 | > BOM: browser object model 浏览器对象模型,里面提供了一些属性和方法,可以让我们操作浏览器 37 | 38 | ### 变量和常量 39 | > 变量: 值是可以变的 40 | > 常量: 值是不可变的 41 | 42 | ```javascript 43 | // 变量 44 | 45 | // -> js中定义变量的方式 46 | // var 变量名 = 值; (ES6中定义变量使用 let ) 47 | var num = 12; 48 | var str = "hello world"; 49 | 50 | // -> Java等后台语言定义变量比较严谨,js比较松散 51 | // int num = 12; 52 | // float num = 12.5; 53 | // double num = 3.1415; 54 | 55 | console.log(num) // -> 12 变量其实只是一个无意义的名字,它所代表的意义都是其存储的那个值 56 | 57 | num = 13; 58 | console.log(num) // -> 13 59 | 60 | ``` 61 | 62 | ```javascript 63 | // 常量 64 | 65 | // -> 任何一个具体的数据值都是常量,例如: 12就是一个常量 66 | 67 | // -> 和变量类似,我们设置一个常量(也是一个名字),给其储存一个值,但是这个存储的值不能修改 68 | 69 | const num = 12; // -> 定义一个常量num,给他存储了12 70 | num = 13; // -> Uncaught TypeError: Assignment to constant variable. 常量分配的值是不能修改的 71 | 72 | ``` 73 | 74 | ### JS的命名规范 75 | 76 | 1. js中严格区分大小写 77 | 78 | ```javascript 79 | var name = "lilei"; 80 | var Name = "hanmeimei"; 81 | console.log(name) // -> lilei 82 | // -> name和Name是两个不同的变量 83 | ``` 84 | 85 | 2. 遵循国际命名规则,`驼峰命名法` `下划线命名法` 86 | 87 | > 第一个单词首字母小写,其余每个有意义的单词首字母大写; 88 | > 以下划线分割两个单词; 89 | > 数字字母下划线$都可以用于命名,但不能以数字开头 90 | > 关键字/保留字不能作为变量名; 91 | 92 | ```javascript 93 | var firstName; 94 | var first_name; 95 | 96 | add / insert / create : 增加创建插入 97 | remove / rm / clear / del : 删除清空 98 | update : 修改升级 99 | get / query / select : 查询获取 100 | ``` 101 | -------------------------------------------------------------------------------- /js-exercise/001control-div.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 控制div 9 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 48 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十七之预解释的特殊处理及上级作用域.md: -------------------------------------------------------------------------------- 1 | #### 预解释机制 2 | in: "num" in window 判断num是否为window这个对象的一个属性, 是的话返回true, 不是的话返回false 3 | 4 | ```javascript 5 | var obj = {name:"lilei",age:18} 6 | console.log("name" in obj) // -> true; 7 | console.log("sex" in obj) // -> false 8 | ``` 9 | 10 | --- 11 | 12 | 1. 预解释的时候不管条件是否成立, 都要把带var的进行提前声明 13 | window的预解释: var num -> window.num; 14 | 15 | ```javascript 16 | if(!("num" in window)){ 17 | var num = 12; 18 | } 19 | console.log(num) // -> undefined 20 | ``` 21 | --- 22 | 23 | 2. 预解释的时候只预解释 "=" 左边的,右边的是值, 不参与预解释 24 | 25 | ```javascript 26 | // 匿名函数之函数表达式: 把函数定义的部分当做一个值赋值给我们的变量/元素的某一个事件 27 | var fn = function (){ 28 | console.log("ok") 29 | } 30 | 31 | fn(); 32 | function fn(){ 33 | console.log("ok") 34 | } 35 | fn(); 36 | ``` 37 | 38 | --- 39 | 40 | 3. 自执行函数定义的那个function在全局作用域下不进行预解释,当代码执行到这个位置的时候定义和执行一起完成了; 41 | 自执行函数: 定义和执行一起完成 42 | 43 | ```javascript 44 | (function(num){})(100); 45 | ~function(num){}(100); 46 | -function(num){}(100); 47 | +function(num){}(100); 48 | !function(num){}(100); 49 | ``` 50 | 51 | --- 52 | 53 | 4. 函数体中return 下面的代码虽然不在执行了,但是需要进行预解释; return后面跟着的都是我们返回的值,所以不进行预解释 54 | 55 | ```javascript 56 | function fn(){ 57 | console.log(num); // -> undefined 58 | return function(){ 59 | 60 | } 61 | var num = 100; 62 | } 63 | fn(); 64 | ``` 65 | 66 | --- 67 | 68 | 5. 如果在预解释的时候,如果名字已经声明过了,不需要重新的声明,但需要重新的赋值; 69 | 在js中如果变量名和函数名重复了,也算冲突了 70 | 预解释: var fn; window.fn; fn = xxxfff000 window.fn = xxxfff000 71 | 72 | 73 | ```javascript 74 | var fn = 12; 75 | function fn(){ 76 | console.log("ok"); 77 | } 78 | 79 | // 预解释: 80 | // 声明+定义 81 | fn(); // -> 2 82 | function fn(){console.log(1)}; 83 | fn(); // -> 2 84 | var fn = 10; 85 | fn(); // -> 10() error: fn is not a function 86 | function fn(){console.log(2)}; 87 | fn(); 88 | ``` 89 | 90 | #### 查找上级作用域 91 | 92 | ```javascript 93 | var num = 12; 94 | function fn(){ 95 | var num = 120; 96 | return function(){ 97 | console.log(num); 98 | } 99 | } 100 | var f = fn(); 101 | f(); // -> 120 102 | ~function () { 103 | f(); // -> 120 104 | }(); 105 | ``` 106 | **如何查找当前作用域的上一级作用域?** 107 | - 看当前函数是在哪个作用域下定义的,那么它的上级作用域就是谁 -> 和函数在哪执行的没有任何关系 108 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记五十一之js盒子模型.md: -------------------------------------------------------------------------------- 1 | #### js盒子模型 2 | 3 | CSS盒子模型 ,margin - border - padding - content 4 | 5 | JS盒子模型指的是通过js中提供的一系列属性和方法,获取页面中元素的样式信息值 6 | 7 | ```html 8 |
这是一个盒子
9 | 13 | ``` 14 | > 内容的高度和宽度: 我们设置的width/height这两个样式就是内容的宽和高; 如果没有设置height值,容器的高度会根据里面内容自己进行适应,这样获取的值就是真是内容的高;如果设置固定的高度了,不管内容是多了还是少了,其实我们内容的高度指的都是设定的那个值; 15 | > 真是内容的高度和宽度: 这个代指的是实际内容的宽高(和设置的height没有必然的关系),例如:设置高度为200px,如果内容有益处,那么真实内容的高度是把移除内容的高度也加进来 16 | 17 | 1. client系列(当前元素的几个私有属性) 18 | 19 | > clientWidth/clientHeight: 内容的高度/宽度+左右/上下填充(和内容溢出来没有关系) 20 | > clientTop/clientBottom/clientLeft/clientRight: 上/下/左/右边框的的宽度 21 | 22 | 2. offset系列 23 | 24 | > offsetWidth/offsetHeight: clientWidth/clientHeight+左右/上下边框(和内容溢出来没有关系) 25 | > offsetParent: 当前元素的父级参照物 26 | > offsetTop/offsetBottom/offsetLeft/offsetRight 当前元素的外边框距离父级参照物的内边框的偏移量 27 | 28 | 3. scroll系列 29 | 30 | > scrollWidth/scrollHeight: 和我们的clientWidth/clientHeight一模一样(前提是容器中的内容没有溢出的情况下) 31 | > 如果容器内容有溢出,我们获取的结果是如下规则: 32 | > scrollWidth: 真实内容的宽度(包含溢出)+左填充 33 | > scrollHeight: 真实内容的高度(包含溢出)+上填充 34 | > 获取的结果都是约等于值: 35 | > 因为在同一个浏览器中是否设置了`overflow="hidden"`对于最终的结果是有影响的; 在不同的浏览器中我们获取到的结果也是不同的 36 | > scrollLeft/scrollTop: 滚动条卷去的宽度/高度 37 | 38 | ##### 关于js盒子模型属性取值的问题 39 | 40 | > 通过这13个属性值获取的结果永远不可能出现小数,都是整数;浏览器获取结果的时候,在原来真实的结果上自动四舍五入 41 | 42 | ##### 关于浏览器本身的盒子模型信息 43 | 44 | > clientWidth/clientHeight 是当前浏览器可是窗口的(一屏幕的)宽度/高度 45 | > scrollWidth/scrollHeight 是当前页面的额真实宽度和高度(所有屏加起来的宽度和高度)但是是一个约等于的值 46 | > 不管哪些属性,也不管是什么浏览器,也不管是获取还是设置,想要都兼容的话,需要写两套 47 | 48 | ```javascript 49 | // 获取 50 | document.documentElement[attr]||document.body[attr] 51 | // 设置 52 | document.documentElement.scrollTop = 0; 53 | document.document.scrollTop = 0; 54 | 55 | // 封装一个关于浏览器盒子模型的方法 56 | // 如果只传递了attr没有传递value,默认的意思是获取样式值 57 | // 如果两个参数都传递了,意思是设置某一样式属性的值 58 | // 不严谨的来说这就是有关于"类的重载":同一个方法,通过传递参数的不同实现了不同的功能 59 | function win(attr, value){ 60 | if(typeof value === "undefined"){ 61 | // 没有传递value值 -> "获取" 62 | return document.documentElement[attr] || document.body[attr]; 63 | } 64 | document.documentElement[attr] = value; 65 | document.body[attr] = value; 66 | } 67 | win("scrollTop") // -> 获取 68 | win("scrollTop",10) // -> 设置 69 | ``` 70 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十八之Date日期.md: -------------------------------------------------------------------------------- 1 | ### Date日期操作基础讲解 2 | 3 | > Date是日期类,通过它可以对时间进行处理 4 | 5 | ```javascript 6 | var time = new Date(); 7 | // -> 获取当前客户端本机时间(当前获取的时间不能作为重要的参考依据) 8 | // -> 获取的结果是一个日期格式的对象: 9 | // -> Thu May 10 2018 14:14:29 GMT+0800 (中国标准时间) 10 | 11 | typeOf new Date() // -> "object" 12 | 13 | time.getFullYear() // -> 获取四位整数年 14 | time.getMonth() // -> 获取的月 0~11,代表1~12月 15 | time.getDate() // -> 获取日 1~31 16 | time.getDay() // -> 获取星期(0~6代表周日到周六) 17 | time.getHours() // -> 获取小时 18 | time.getMinutes() // -> 获取分钟 19 | time.getSeconds() // -> 获取秒 20 | time.getMilliseconds() // -> 获取毫秒 21 | time.getTime() // -> 获取当前日期距离 '1970-01-01 00:00:00' 的毫秒差 22 | ``` 23 | 24 | ```javascript 25 | var time = new Date('2018-05-09'); 26 | // -> 当new Date中传递一个时间的字符串,相当于把这个字符串转换为标准时间对象格式(转换完成后,就可以调取上面那些方法了) 27 | 28 | // -> 时间格式的字符串 29 | // -> '2018-05-09' (ie下识别不了) 30 | // -> '2018/05/09' 31 | // -> '2018/05/09 21:12:13' 32 | // -> 1525933730685 (如果传递的是距离1970年的毫秒差,也可以识别转换,但是只能是数字不能是字符串) 33 | // -> ... 34 | ``` 35 | 36 | ```html 37 | 42 |
距离汶川地震十周年:00:00:00 43 |
44 | 76 | ``` 77 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十六之DOM基础-节点.md: -------------------------------------------------------------------------------- 1 | ### DOM的节点 2 | 3 | > node: 节点,浏览器认为在一个html页面中的所有内容都是节点(包括标签,注释,文字文本等) 4 | > 5 | > - 元素节点: html标签 6 | > - 文本节点: 文字内容(高版本浏览器会把空格和换行当做文本节点) 7 | > - 注释节点: 注释内容 8 | > - document: 文档节点 9 | > - ... 10 | 11 | - **元素节点** 12 | 13 | > nodeType: 1 14 | > nodeName: 大写标签名(在部分浏览器的怪异模式下,我们写的标签名是小写, 它获取的就是小写...) 15 | > nodeValue: null 16 | > 17 | > [curEle].tagName: 获取当前元素的标签名(获取的标签名一般都是大写) 18 | 19 | - **文本节点** 20 | 21 | > nodeType: 3 22 | > nodeName: #text 23 | > nodeValue: 文本内容 24 | 25 | - **注释节点** 26 | 27 | > nodeType: 8 28 | > nodeName: #comment 29 | > nodeValue: 注释内容 30 | 31 | - **文档节点** 32 | 33 | > nodeType: 9 34 | > nodeName: #document 35 | > nodeValue: null 36 | 37 | 节点就是用来描述页面中每一个部分之间关系的,只要我可以获取页面中的一个节点,那么我就可以通过相关的属性和方法获取页面中的所有节点; 38 | 39 | ```html 40 |
41 |
    42 |
  • 页卡1
  • 43 |
  • 页卡2
  • 44 |
  • 页卡3
  • 45 |
46 |
内容1
47 |
内容2
48 |
内容3
49 |
50 | ``` 51 | 52 | - childNodes 53 | 54 | > 获取当前元素所有的子节点(节点集合: 类数组) 55 | > 注: 不仅仅是元素子节点, `文本`, `注释`等都会包含在内; 56 | > 子节点说明只是在儿子辈分中查找到(孙子及后代不在内) 57 | 58 | ```javascript 59 | var box=document.getElementById('box') 60 | console.log(box.childNodes) 61 | // NodeList(9) [text, ul, text, div, text, div, text, div, text] 62 | ``` 63 | 64 | - children 65 | 66 | > 获取所有的元素子节点(元素集合) 67 | > 不包含`文本`/`注释` 68 | > 在ie6~8下获取的结果和标准浏览器中有区别(ie6~8中会把注释节点当做元素节点获取到) 69 | 70 | ```javascript 71 | console.log(box.children) 72 | // HTMLCollection(4) [ul, div, div, div] 73 | ``` 74 | 75 | - parentNode 76 | 77 | > 获取当前元素的父节点(元素对象) 78 | 79 | ```javascript 80 | console.log(box.parentNode) 81 | // ... 82 | ``` 83 | 84 | - previousSibling & nextSibling 85 | 86 | > `previousSibling`: 获取当前节点的上一个哥哥节点(不一定是元素节点也可能是文本或者注释) 87 | > `nextSibling`: 获取当前节点的上一个弟弟节点(不一定是元素节点也可能是文本或者注释) 88 | 89 | - previousElementSibling & nextElementSibling 90 | 91 | > `previousElementSibling`: 获取当前节点的上一个哥哥元素节点 92 | > `nextElementSibling`: 获取当前节点的下一个弟弟元素节点 93 | > ie6~8下不兼容 94 | 95 | - fristChild & lastChild 96 | 97 | > `fristChild`: 当前元素所有子节点中的第一个(也不一定是元素节点,可能是文本和注释) 98 | > `lastChild`: 当前元素所有子节点中的最后一个(也不一定是元素节点,可能是文本和注释) 99 | 100 | - fristElementChild & lastElementChild 101 | 102 | > `fristElementChild`: 当前元素中的第一个元素子节点 103 | > `lastElementChild`: 当前元素中的最后一个元素子节点 104 | > ie6~8下不兼容 105 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十四之原型链模式扩展(1).md: -------------------------------------------------------------------------------- 1 | ### 原型链模式扩展 2 | 3 | ##### 批量设置原型上的公有属性 4 | ```javascript 5 | function Fn(){ 6 | this.x = 100; 7 | } 8 | Fn.prototype.getX = function(){ 9 | }; 10 | Fn.prototype.getY = function(){ 11 | }; 12 | Fn.prototype.getZ = function(){ 13 | }; 14 | var f1 = new Fn; 15 | ``` 16 | 1. 起一个别名 17 | 18 | ```javascript 19 | function Fn(){ 20 | this.x = 100; 21 | } 22 | var pro = Fn.prototype; 23 | // 把原来原型指向的地址赋值给pro,现在它们操作的是同一个内存空间 24 | pro.getX = function(){ 25 | }; 26 | pro.getY = function(){ 27 | }; 28 | pro.getZ = function(){ 29 | }; 30 | var f1 = new Fn; 31 | ``` 32 | 33 | 2. 重构原型对象的方式 -> 自己新开辟一个堆内存,存储我们共有的属性和方法,把浏览器原来给Fn.prototype开辟的那个替换掉 34 | 35 | ```javascript 36 | function Fn(){ 37 | this.x = 100; 38 | } 39 | Fn.prototype = { 40 | constructor: Fn, // 手动添加constructor 41 | x: function(){ 42 | 43 | }, 44 | y: function(){ 45 | 46 | } 47 | }; 48 | var f1 = new Fn; 49 | f.a(); 50 | f.b(); 51 | 52 | //1. 只有浏览器天生给Fn.prototype 开辟的堆内存里面才有constructor, 53 | // 而我们自己开辟的这个堆内存没有这个属性,这样constructor指向就不再是Fn而是Object了 54 | 55 | // 为了和原来的保持一致, 我们需要手动的增加constructor的指向 56 | 57 | console.log(f.constructor) // -> (没做任何处理之前) Object 58 | ``` 59 | a. 只有浏览器天生给Fn.prototype 开辟的堆内存里面才有constructor, 而我们自己开辟的这个堆内存没有这个属性,这样constructor指向就不再是Fn而是Object了 60 | 为了和原来的保持一致, 我们需要手动的增加constructor的指向 61 | 62 | ```javascript 63 | function Fn(){ 64 | this.x = 100; 65 | } 66 | Fn.prototype = { 67 | constructor: Fn, // 手动添加constructor 68 | y: function(){ 69 | 70 | }, 71 | z: function(){ 72 | 73 | } 74 | }; 75 | var f1 = new Fn; 76 | f1.y(); 77 | f1.z(); 78 | console.log(f1.constructor) // ->Fn(){ this.x = 100; } 79 | ``` 80 | b. 用这种方式给内置类增加公有的属性 81 | 给内置类Array增加数组去重的方法 82 | 83 | ```javascript 84 | Array.prototype = { 85 | constructor: Array, 86 | unique: function(){ 87 | 88 | } 89 | } 90 | ``` 91 | 92 | > 这种方式会把之前已经存在于原型上的属性和方法给替换掉, 所以用这种凡是修改内置类的话,浏览器是会屏蔽掉的 93 | 94 | ```javascript 95 | var ary = [1,2,2,1,2,3,4,2,1,3]; 96 | ary.sort(); 97 | console.log(ary); // -> [1, 1, 1, 2, 2, 2, 2, 3, 3, 4] 98 | ``` 99 | > 但是可以一个个的修改内置的方法,当我们通过下述方式在数组的原型上增加方法,如果方法名和原来内置的重复了,会把人家内置的修改掉 -> 以后在内置类的原型上增加方法,命名都需要加特殊的前缀; 100 | 101 | ```javascript 102 | Array.prototype.sort = function(){ 103 | console.log(this) // this -> ary 当前要操作的这个数组 104 | // [1,2,2,1,2,3,4,2,1,3] 105 | } 106 | var ary = [1,2,2,1,2,3,4,2,1,3]; 107 | ary.sort(); 108 | console.log(ary); // -> [1,2,2,1,2,3,4,2,1,3] 109 | ``` 110 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十之单例模式和工厂模式.md: -------------------------------------------------------------------------------- 1 | 2 | ### 单例模式 3 | 4 | ##### 对象数据类型的作用: 5 | > 把描述同一个实物(同一个对象)的属性和方法放在一个内存空间下,起到了分组的作用,这样不同事物之间的属性即使属性名相同, 相互也不会发生冲突 6 | > --- 这种分组编写代码的模式叫做: **单例模式** 7 | 8 | > 在单例模式中我们把person1或person2叫做"命名空间" 9 | 10 | ```javascript 11 | var person1 = { 12 | name:"lilei", 13 | age:18 14 | } 15 | var person2 = { 16 | name:"hanmeimei", 17 | age:16 18 | } 19 | ``` 20 | 21 | 单例模式是一种项目中经常使用的模式, 因为项目中可以使用单例模式来进行"**模块化开发**" 22 | 23 | **模块化开发**: 对于一个相对来说比较大的项目, 需要多人协作的开发的, 我们一般情况下会根据当前项目的需求划分成几个功能板块, 每个人负责一部分, 同时开发, 最后把每个人的代码进行合并 24 | 25 | ```javascript 26 | var utils = { 27 | select: function(){ 28 | 29 | } 30 | } 31 | var tabRender = { 32 | change: function(){ 33 | utils.select(); // 在自己的命名空间下调用其他命名空间的方法 34 | } 35 | } 36 | var searchRender = { 37 | change: function(){ 38 | searchRender.clickEven(); // 在自己的命名空间下调用自己命名空间的方法 39 | // this.clickEven() 40 | } 41 | clickEven: function(){ 42 | 43 | } 44 | } 45 | ``` 46 | 47 | ### 工厂模式 48 | 49 | ```javascript 50 | // 单例模式 51 | var jsPerson1 = { 52 | name:'lilei', 53 | age:18, 54 | writeJs: function(){ 55 | console.log("my name is " + this.name + ",I can write JS!") 56 | } 57 | } 58 | jsPerson1.writeJs(); 59 | 60 | var jsPerson2 = { 61 | name:'hanmeimei', 62 | age:16, 63 | writeJs: function(){ 64 | console.log("my name is " + this.name + ",I can write JS!") 65 | } 66 | } 67 | jsPerson2.writeJs(); 68 | 69 | // ... 70 | ``` 71 | 72 | > `单例模式`虽然解决了分组的作用,但是不能实现批量的生产,属于手工作业模式, 引出-> "`工厂模式`" 73 | > 把实现同一件事情的相同的代码放到一个函数中, 以后如果再想实现这个功能, 不需要重新的编写这些代码了, -> "`函数的封装`" 74 | > --> `低耦合高内聚`: 减少页面中的冗余代码,提高代码的重复利用率 75 | 76 | ```javascript 77 | function createJsPerson(name,age){ 78 | var obj = {}; 79 | obj.name = name; 80 | obj.age = age; 81 | obj.writeJs = function(){ 82 | console.log("my name is "+ this.name +", I can write JS!"); 83 | } 84 | return obj; 85 | } 86 | var p1 = createJsPerson('lilei',18); 87 | p1.writeJs(); 88 | 89 | var p2 = createJsPerson('hanmeimei',16); 90 | p1.writeJs(); 91 | ``` 92 | > js是一门轻量级的脚本"编程语言"(html+css不属于编程语言,属于标记语言) 93 | > 所有的编程语言都是面向对象开发的 -> 类的继承, 封装, 多态 94 | > `继承`: 子类继承父类中的属性和方法 95 | > `多态`: 当前方法的多种形态(在后台语言中: 多态包含`重载`和`重写`) 96 | > `重载`: js中不存在重载, 方法名一样的话, 后面的会把前面的覆盖掉,最后只保留一个;(js中有一个操作类似重载但不是重载:我们可以根据传递的参数不一样,实现不同的功能) 97 | 98 | ```javascript 99 | function sum(num){ 100 | if(typeof num === "undefined"){ 101 | return 0; 102 | } 103 | return num; 104 | } 105 | sum(100); 106 | sum(); 107 | ``` 108 | 109 | > `重写`: 子类重写父类的方法 110 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十一类数组转换为数组(浏览器异常捕获).md: -------------------------------------------------------------------------------- 1 | #### 类数组转换为数组 2 | 3 | ```html 4 |
5 |
6 |
7 |
8 |
9 | 16 | ``` 17 | 18 | ```html 19 |
20 |
21 |
22 |
23 |
24 | 38 | ``` 39 | 40 | #### 浏览器异常信息捕获 41 | 42 | > js中使用try catch进行浏览器的异常信息捕获 43 | 44 | ```javascript 45 | console.log(num) // -> Uncaught ReferenceError: num is not defined 46 | // 在浏览器中本行信息报错,后面的代码都不再执行了 47 | console.log("ok") 48 | ``` 49 | ```javascript 50 | try{ 51 | // 52 | }catch(e){ 53 | // 如果代码报错执行catch中的代码 54 | }finally{ 55 | //一般不用: 不管try中的代码是否报错,都要执行finally中的代码 56 | } 57 | ``` 58 | 59 | - 第二行代码报错,如果用try/catch捕获了异常信息,不影响下面的代码继续执行; 如果try中的代码执行出错了,会默认的执行catch中的代码 60 | 61 | ```javascript 62 | try{ 63 | console.log(num) 64 | }catch(e){ // -> 形参必须要写,我们一般起名为e 65 | console.log(e.message) // -> num is not defined 66 | // 收集代码报错信息 67 | } 68 | console.log("ok") // ok 69 | ``` 70 | > 有时候既想捕获到错误的信息, 又想不让下面的代码继续执行 71 | 72 | ```javascript 73 | try{ 74 | console.log(num) 75 | }catch(e){ 76 | // console.log(e.message); -> 可以得到错误的信息,把其进行统计 77 | 78 | // 手动抛出一条错误信息, 终止代码执行 79 | throw new Error("当前网络繁忙,请稍后再试...") 80 | } 81 | console.log("ok") 82 | ``` 83 | - new Error -> 错误实例 84 | - new TypeError -> 引用错误 85 | - new ReferenceError -> 类型错误 86 | - new RangeError -> 范围错误 87 | 88 | 89 | ```javascript 90 | var utils = { 91 | listToArray: function(likeAry){ 92 | var ary = []; 93 | try{ 94 | ary = Array.prototype.slice.call(likeAry); 95 | }catch(e){ 96 | for(var i=0;i 5 | li{ 6 | list-style: none; 7 | } 8 | #ul1{ 9 | width: 150px; 10 | margin: 20px auto; 11 | } 12 | #ul1 li{ 13 | border-bottom: 1px solid #aaa; 14 | } 15 | 16 |
    17 |
  • 67
  • 18 |
  • 64
  • 19 |
  • 61
  • 20 |
  • 69
  • 21 |
  • 65
  • 22 |
23 | 24 | 41 | ``` 42 | 43 | #### DOM映射机制 44 | 45 | - 页面中的标签和js中获取到的元素对象(元素集合)是紧紧地绑定在一起的,页面中的HTML结构改变,js中不需要重新获取,集合里面的内容也会跟着自动改变 46 | 47 | 48 | #### 初识AJAX 49 | 50 | ```html 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 | 92 | ``` 93 | 94 | ```javascript 95 | // 1. 首先创建一个Ajax对象 96 | var xhr = new XMLHttpRequest(); 97 | 98 | // 2. 打开需要请求数据的那个文件地址 99 | xhr.open("get", "data.txt", true) // true 异步请求 100 | 101 | // 3. 监听请求状态 102 | xhr.onreadystatechange = function (){ 103 | if(xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)){ 104 | var val = xhr.responseText; 105 | console.log(val) 106 | } 107 | } 108 | 109 | // 4. 发送请求 110 | xhr.send(null); 111 | ``` 112 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十七之正则表达式(3).md: -------------------------------------------------------------------------------- 1 | #### 正则的捕获 exec 2 | 3 | - 捕获的内容格式 4 | 5 | 每一次捕获的时候都是先进行默认的匹配,如果没有匹配成功的,捕获到额结果是null;只有有匹配的内容才能捕获到 6 | 7 | 1) 捕获到的内容是一个数组 8 | 数组中的第一项是但钱大正则捕获的内容 9 | ` index ` : 捕获内容在字符串中开始的索引位置 10 | ` input ` : 捕获的原始字符串 11 | 2) 正则捕获的特点 12 | **懒惰性**: 每一次执行exec值捕获第一个匹配的内容, 在不进行任何处理的情况下, 再执行多次捕获, 捕获的还是第一个匹配的内容 13 | **贪婪性**: 正则的每一次捕获都是按照匹配最长的结果捕获的,例如: 2符合正则/2015页符合正则,我们默认捕获的是2015 14 | 15 | ```javascript 16 | var reg = /\d+/; 17 | var str = "lilei18hanmeimei16"; 18 | 19 | console.log(reg.lastIndex) // -> 0 20 | console.log(reg.exec(str)); // -> ["18", index: 5, input: "lilei18hanmeimei16", groups: undefined] 21 | 22 | console.log(reg.lastIndex) // -> 0 23 | console.log(reg.exec(str)); // -> ["18", index: 5, input: "lilei18hanmeimei16", groups: undefined] 24 | ``` 25 | 26 | ##### 如何解决正则的懒惰性? 27 | 28 | > 在正则的末尾加上一个修饰符"g" ; 29 | 30 | **修饰符** : ` g `:全局匹配, ` i ` : 不区分大小写 ` m ` : 多行匹配 31 | 32 | > 原理: 加了全局修饰符 g, 正则每一次捕获结束后,我们的lastIndex的值都变为了最新的值,下一次捕获从最新的位置开始查找,这样就可以把所有需要捕获的内容都获取到了 33 | 34 | ```javascript 35 | var reg = /\d+/g; 36 | var str = "lilei18hanmeimei16"; 37 | 38 | console.log(reg.lastIndex) // -> 0 39 | console.log(reg.exec(str)); // -> ["18", index: 5, input: "lilei18hanmeimei16", groups: undefined] 40 | 41 | console.log(reg.lastIndex) // -> 7 42 | console.log(reg.exec(str)); // -> ["16", index: 16, input: "lilei18hanmeimei16", groups: undefined] 43 | 44 | console.log(reg.lastIndex) // -> 18 45 | console.log(reg.exec(str)); // -> null 46 | ``` 47 | 48 | 一次性匹配所有符合条件的内容(加 ` g ` 全局匹配) 49 | 50 | ```javascript 51 | var reg = /\d+/g; 52 | var str = "lilei18hanmeimei16lihua17"; 53 | var ary = []; 54 | var res = reg.exec(str); 55 | while(res){ 56 | ary.push(res[0]); 57 | res = reg.exec(str); 58 | } 59 | console.log(ary); // -> ["18", "16", "17"] 60 | ``` 61 | 62 | ##### 如何解决正则的贪婪性? 63 | 64 | > 在量词元字符后面添加一个 ` ? ` 即可 65 | 66 | ```javascript 67 | var reg = /\d+?/g; 68 | var str = "lilei18hanmeimei16lihua17"; 69 | console.log(reg.exec(str)); // -> 2 70 | ``` 71 | 72 | ##### ` ? ` 在正则中有很多的作用: 73 | 1. 放在普通的额元字符后面代表出现0-1次 ` /\d?/ ` 74 | 2. 放在一个量词的元字符后面代表取消捕获时候的贪婪性 75 | 76 | ```javascript 77 | var reg = /\d+?/g; 78 | var str = "lilei18hanmeimei16lihua17"; 79 | var ary = []; 80 | var res = reg.exec(str); 81 | while(res){ 82 | ary.push(res[0]); 83 | res = reg.exec(str); 84 | } 85 | console.log(ary); // -> ["1", "8", "1", "6", "1", "7"] 86 | ``` 87 | 88 | 字符串中的match方法 -> 把所有和正则匹配的字符串都获取到 89 | 90 | ```javascript 91 | var reg = /\d+?/g; 92 | var str = "lilei18hanmeimei16lihua17"; 93 | var ary = str.match(reg); 94 | console.log(ary) // -> ["1", "8", "1", "6", "1", "7"] 95 | ``` 96 | > 虽然在当前的情况下match比我们的exec更加的简便一些,但是match中存在一些自己处理不了的问题: 在分组捕获的情况下,match只能捕获到大正则匹配的内容,而对于小正则捕获的内容是无法获取的 97 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十二之sort深入研究.md: -------------------------------------------------------------------------------- 1 | ##### 数组排序 2 | 3 | ```javascript 4 | var ary = [12,23,14,34,23,1,14,16,26,2]; 5 | // ary.sort(); // 只按第一位数字进行排序(只能排10以内的数字) 6 | ary.sort(function(a,b){ 7 | return a-b; 8 | }) 9 | console.log(ary) // [1, 2, 12, 14, 14, 16, 23, 23, 26, 34] 10 | ``` 11 | 12 | - 回调函数 13 | 14 | > 把一个方法A当做参数值传递给另一个函数B, 然后在B执行的过程中, 我们随时根据需求让A方法执行; 15 | 16 | ```javascript 17 | function A(){ 18 | 19 | } 20 | function B(fn){ 21 | fn(); 22 | fn(); 23 | fn(); 24 | } 25 | B(A); 26 | ``` 27 | 28 | ```javascript 29 | var ary = [12,23,14,34,23,1,14,16,26,2]; 30 | ary.sort(function(a,b){ 31 | console.log(a,b) 32 | // 12 23 33 | // 23 14 34 | // 14 34 35 | // 34 23 36 | // 23 1 37 | // 1 14 38 | // 14 16 39 | // 16 26 40 | // 26 2 41 | 42 | // a -> 每一次执行匿名函数的时候,找到数组中的当前项 43 | // b -> 当前项的后一项 44 | 45 | // return a-b; // -> 升序 如果a>b,返回的>0, a和b 交换位置 46 | // return b-a; // -> 降序 如果b>a,返回的>0,a和b变换位置 47 | // return 的值是一个 > 0 或 <= 0 如果大于0 让a和b交换位置,小于等于0原来位置不变 48 | }) 49 | ``` 50 | 51 | ```javascript 52 | var ary = [12,23,14,34,23,1,14,16,26,2]; 53 | ary.sort(function(a,b){ 54 | return 1; 55 | }) 56 | console.log(ary) // [2, 26, 16, 14, 1, 23, 34, 14, 23, 12] 57 | // 不管a和b谁大, 每一次都返回一个恒大于零的数, 也就是每一次a和b都要交换位置, 最后的结果就是原有数组倒过来排列了 58 | // 相当于reverse 59 | ``` 60 | #### 二维数组 61 | 62 | > 二维数组排序 63 | 64 | ```javascript 65 | var ary = [ 66 | {name:"李雷",age:18}, 67 | {name:"韩梅梅",age:16}, 68 | {name:"王二",age:23}, 69 | {name:"赵四",age:32} 70 | ] 71 | // 给二维数组排序,按照年龄由小到大排序 72 | 73 | ary.sort(function(a,b){ 74 | return a.age - b.age; 75 | }) 76 | console.log(ary) 77 | // {name: "韩梅梅", age: 16} 78 | // {name: "李雷", age: 18} 79 | // {name: "王二", age: 23} 80 | // {name: "赵四", age: 32} 81 | ``` 82 | ```javascript 83 | var ary = [ 84 | {name:"李雷",age:18}, 85 | {name:"韩梅梅",age:16}, 86 | {name:"王二",age:23}, 87 | {name:"赵四",age:32} 88 | ] 89 | // 给二维数组排序,按照年龄由大到小排序 90 | 91 | ary.sort(function(a,b){ 92 | return (a.age - b.age)*-1; 93 | }) 94 | console.log(ary) 95 | // {name: "韩梅梅", age: 16} 96 | // {name: "李雷", age: 18} 97 | // {name: "王二", age: 23} 98 | // {name: "赵四", age: 32} 99 | ``` 100 | 101 | > 按姓名排序 localeCompare() 102 | 103 | ```javascript 104 | var ary = [ 105 | {name:"李雷",age:18}, 106 | {name:"韩梅梅",age:16}, 107 | {name:"王二",age:23}, 108 | {name:"赵四",age:32} 109 | ] 110 | ary.sort(function(a,b){ 111 | return a.name.localeCompare(b.name); 112 | }) 113 | console.log(ary) 114 | // {name: "李雷", age: 18} 115 | // {name: "王二", age: 23} 116 | // {name: "赵四", age: 32} 117 | // {name: "韩梅梅", age: 16} 118 | ``` 119 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十六之预解释.md: -------------------------------------------------------------------------------- 1 | #### js中的数据类型 2 | - 基本数据类型 3 | + string 4 | + number 5 | + undefined 6 | + null 7 | + Boolean 8 | - 引用数据类型 9 | + 对象 10 | + {} 对象 11 | + [] 数组 12 | + /^$/ 正则 13 | + Date 日期 14 | + function 15 | 16 | ```javascript 17 | var num = 12; 18 | 19 | var obj = {name:"lilei",age:18} 20 | 21 | function fn(){ 22 | console.log("好好学习,天天向上") 23 | } 24 | console.log(fn) // -> 把整个函数的定义部分(函数本身)在控制台输出 25 | console.log(fn()) // -> 把当前函数执行的返回结果 return 后面写的是啥 26 | //返回的值就是啥,如果没有return,默认返回undefined 27 | ``` 28 | 29 | 1. 当浏览器加载html页面的时候,首先会提供一个供全局js代码执行的环境 -> 全局作用域(global/window) 30 | 31 | 2. **预解释(变量提声)**: 32 | 在当前的作用域中,js代码执行之前,浏览器首先会默认把所有带var和function的进行提前的声明或者定义 33 | 1. 理解声明和定义 34 | var num = 12; 35 | `声明(declare)`: var num; -> 告诉浏览器在全局作用域中有一个num的变量了-> 如果一个变量只是声明,但是没有赋值,默认值是undefined 36 | `定义(defined)`: num=12; -> 给变量进行赋值 37 | 2. 对于带var和function关键字的在预解释的时候操作还是不一样的 38 | `var -> 在预解释的时候只是提前的声明` 39 | `function -> 在预解释的时候提前声明 + 定义都完成了` 40 | 3. 预解释只发生在当前的作用域中,例如: 开始只对window下的进行预解释, 只有函数执行的时候才会对函数中的进行预解释 41 | 3. js中内存的分类 42 | `栈内存`: 用来提供一个供js代码执行的环境 -> 作用域(全局作用域/私有作用域) 43 | `堆内存`: 用来存储引用数据类型的值 -> 对象存储的是属性名和属性值, 函数存储的是代码字符串... 44 | 45 | ```javascript 46 | console.log(num) // -> undefined 不可以在上面执行,因为 var 预解释只声明不定义 47 | var num = 12; 48 | console.log(num) // -> 12 49 | var obj = {name:"lilei",age:18} 50 | 51 | fn(100,200) // -> 300 可以在上面执行,因为函数在预解释的时候声明和定义就已经完成了 52 | function fn(num1,num2){ 53 | total = num1 + num2; 54 | console.log(total) 55 | } 56 | ``` 57 | 58 | 1. 如何区分全局变量和私有变量: 59 | a. 在全局作用域下声明(预解释的时候)的变量是全局变量; 60 | b. 在"私有作用域中声明的变量"和"函数的形参"都是私有的变量; 61 | 在私有作用域中,代码执行的时候遇到了一个变量,首相我们需要确定他是否为私有的变量,如果是私有的变量,那么和外面的没有任何关系,如果不是私有的,则往当前作用域的上一级作用域进行查找,如果上级作用域也没有则继续查找,一直找到window为止...(作用域链) 62 | 63 | 64 | 2. 当函数执行的时候(直接目的: 让函数体中的代码执行), 首先会形成一个新的私有的作用域, 然后按照如下步骤执行: 65 | a. 如果有形参,先给形参赋值 66 | b. 进行私有作用域中的预解释 67 | c. 私有作用域中的代码从上到下执行 68 | d. ... 69 | 70 | 函数形成一个新的私有作用域保护了里面的私有变量不受外界干扰(外面修改不了私有的, 私有的也修改不了外面的) --> **`闭包`** 71 | 72 | --- 73 | 74 | ```javascript 75 | console.log(num1); // -> undefined 76 | var num1 = 12; 77 | console.log(num2); // -> Uncaught ReferenceError: num2 is not defined 78 | num2 = 12; 79 | ``` 80 | 81 | 82 | #### 在全局作用域中, 带var 和不带 var的关系? 83 | **区别**: 84 | - 带var 的可以进行预解释, 所以在赋值的前面执行不会报错; 85 | - 不带var 的是不能预解释的, 在前面执行会报错 86 | 87 | **关系**: 88 | - num2 = 12 -> 相当于给window增加了一个叫做num2的属性名, 属性值是12 89 | - var num1 = 12 -> 首先他相当于给全局作用域增加了一个全局变量num1, 但是不仅如此,它也相当于给window增加了一个属性名num1,属性值是12 90 | 91 | > 私有作用域中出现的一个变量不是私有的,则往上级作用域进行查找,上级没有则继续向上查找,一直找到window为止,如果window下也没有呢? 92 | > 我们要是获取值: 则报错; 93 | > 我们要是设置值: 相当于给window增加了一个属性名 94 | -------------------------------------------------------------------------------- /movie_recommendation/page/index/index.js: -------------------------------------------------------------------------------- 1 | // page/index/index.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | movieList:[{ 9 | movieName:"肖申克的救赎", 10 | movieImg:"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg", 11 | movieEvaluate:"希望让人自由。", 12 | recommend:true, 13 | id: 1292052, 14 | }, { 15 | movieName: "霸王别姬", 16 | movieImg: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p1910813120.jpg", 17 | movieEvaluate: "风华绝代。", 18 | recommend: false, 19 | id: 1291546, 20 | }, { 21 | movieName: "这个杀手不太冷", 22 | movieImg: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p511118051.jpg", 23 | movieEvaluate: "怪蜀黍和小萝莉不得不说的故事。", 24 | recommend: true, 25 | id: 1295644, 26 | }, { 27 | movieName: "阿甘正传", 28 | movieImg: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p510876377.jpg", 29 | movieEvaluate: "一部美国近现代史。", 30 | recommend: false, 31 | id: 1292720, 32 | }, { 33 | movieName: "美丽人生", 34 | movieImg: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p510861873.jpg", 35 | movieEvaluate: "最美的谎言。", 36 | recommend: true, 37 | id: 1292063, 38 | },], 39 | // current:0, 40 | }, 41 | 42 | /** 43 | * 生命周期函数--监听页面加载 44 | */ 45 | onLoad: function (options) { 46 | // console.log(this.data.movieList.length) 47 | this.setData({ 48 | currentIndex:this.data.movieList.length-1 49 | }) 50 | }, 51 | 52 | f0:function(e){ 53 | this.setData({ 54 | currentIndex:this.data.movieList.length-1 55 | }) 56 | }, 57 | 58 | f1:function(e){ 59 | // console.log(e.currentTarget) 60 | var mid = e.currentTarget.dataset.movieId 61 | wx.navigateTo({ 62 | url: '/page/detail/detail?mid=' + mid, 63 | }) 64 | }, 65 | 66 | /** 67 | * 生命周期函数--监听页面初次渲染完成 68 | */ 69 | onReady: function () { 70 | 71 | }, 72 | 73 | /** 74 | * 生命周期函数--监听页面显示 75 | */ 76 | onShow: function () { 77 | 78 | }, 79 | 80 | /** 81 | * 生命周期函数--监听页面隐藏 82 | */ 83 | onHide: function () { 84 | 85 | }, 86 | 87 | /** 88 | * 生命周期函数--监听页面卸载 89 | */ 90 | onUnload: function () { 91 | 92 | }, 93 | 94 | /** 95 | * 页面相关事件处理函数--监听用户下拉动作 96 | */ 97 | onPullDownRefresh: function () { 98 | 99 | }, 100 | 101 | /** 102 | * 页面上拉触底事件的处理函数 103 | */ 104 | onReachBottom: function () { 105 | 106 | }, 107 | 108 | /** 109 | * 用户点击右上角分享 110 | */ 111 | onShareAppMessage: function () { 112 | 113 | } 114 | }) -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十五之正则表达式(1).md: -------------------------------------------------------------------------------- 1 | #### 正则 2 | 3 | - 用来处理字符串的一个规则(正则就是用来处理字符串的) 4 | 5 | 1. 判断一个字符串是否符合我们制定的规则 -> test() - reg.test(str) 6 | 7 | ```javascript 8 | var reg = /\d/; 9 | console.log(reg.test("li")); // -> false 10 | console.log(reg.test("1")); // -> true 11 | console.log(reg.test("li18")); // -> true 12 | ``` 13 | 2. 把字符串中符合正则规则的内容捕获到 -> exec() - reg.exec(str) 14 | 15 | ```javascript 16 | var reg = /\d/; 17 | console.log(reg.exec("li")); // -> null 18 | console.log(reg.exec("1")); // -> ["1", index: 0, input: "1", groups: undefined] 19 | console.log(reg.exec("li18")); // -> ["1", index: 2, input: "li18", groups: undefined] 20 | ``` 21 | 22 | - 如何创建一个正则? 23 | 24 | 1. 字面量创建方式: 25 | 26 | ```javascript 27 | var reg = /\d/; 28 | ``` 29 | 2. 实例创建方式: 30 | 31 | ```javascript 32 | var reg = new RegExp("") 33 | ``` 34 | > 创建对象时,使用字面量和实例没有区别,但是正则的两种创建方式是有区别的 35 | 36 | - 如何学习正则? 37 | 38 | ```javascript 39 | console.dir(RegExp.prototype) 40 | ``` 41 | ![image](https://t1.picb.cc/uploads/2018/06/07/2Pg7xc.png) 42 | 43 | 44 | #### 正则表达式的元字符 45 | 46 | - 每一个正则表达式都是由元字符和修饰符组成的 47 | 48 | ##### 元字符: 在/ /之间具有意义的一些字符 49 | 50 | - 具有特殊意义的元字符 51 | 52 | 1. `\` : 转义字符,转译后面字符所代表的含义; 53 | 2. `^` : 以某一个元字符开始; 54 | 3. **$** : 以某一个元字符结尾; 55 | 4. `\n` : 匹配一个换行符; 56 | 5. `.` : 除了`\n`以外的任意字符; 57 | 6. `()` : 分组 -> 把一个大正则划分为几个小的正则 58 | 7. `x|y` : x或者y中的一个 59 | 8. `[xyz]` : x或者y或者z中的一个 60 | 9. `[^xyz]` : 方括号中的 ^ 读作非, 除了三个以外的任何一个字符 61 | 10. `[a-z]` : 包含a-z之间的任何一个字符 62 | 11. `[^a-z]` : 除了a-z之间的任何一个字符 63 | 12. `\d` : 一个0-9之间的数字 64 | 13. `\D` : 除了0-9之间的数字以外的任何字符 65 | 14. `\b` : 匹配一个边界符 66 | 15. `\w` : 数字/字母/下划线中的任意一个字符 => [0-9a-zA-Z_] 67 | 16. `\s` : 匹配一个空白字符 空格/制表符/换页符 68 | 69 | > 大小写匹配相反 70 | 71 | - 代表出现次数的量词元字符 72 | 73 | 1. `*` : 出现零到多次; 74 | 2. `+` : 出现一到多次; 75 | 3. `?` : 出现零次或者一次; 76 | 4. `{n}` : 出现n次; 77 | 5. `{n,}` : 出现n到多次; 78 | 6. `{n,m}` : 出现n到m次; 79 | 80 | ```javascript 81 | var reg = /^\d$/; // 只能是一个 0-9 之间的数字 82 | console.log(reg.test("9")); // -> true 83 | console.log(reg.test("012")); // -> false 84 | ``` 85 | ```javascript 86 | var reg1 = /^\d+$/; 87 | console.log(reg1.test("9")); // -> true 88 | console.log(reg1.test("012")); // -> true 89 | ``` 90 | ```javascript 91 | var reg = /^0.2$/ // -> 以0开头,以2结尾,中间可以是除了 \n 的任意字符 92 | console.log(reg.test("0.2")); // -> true 93 | console.log(reg.test("0-2")); // -> true 94 | ``` 95 | ```javascript 96 | var reg1 = /^0\.2$/; 97 | console.log(reg1.test("0.2")); // -> true 98 | console.log(reg1.test("0-2")); // -> false 99 | ``` 100 | ```javascript 101 | var reg = /^18|19$/; 102 | // 18,19,181,189,819,1819... 103 | 104 | var reg = /^(18|19)$/ 105 | // 18或19 106 | ``` 107 | 一个简单的手机号的正则: 11位数字,第一位是1 后面10位数字 108 | ```javascript 109 | var reg = /^1\d{10}$/; 110 | ``` 111 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十四之函数的形参与实参.md: -------------------------------------------------------------------------------- 1 | ### 函数中的形参和实参 2 | 3 | > 形参: 相当于生产洗衣机的时候提供的入口,需要用户执行函数的时候把需要的值传递进来,形参是个变量,用来存储和接受这些值 4 | > 实参: 用户执行的时候传递给形参的具体值 5 | 6 | ```javascript 7 | // 随便求出两个数的和 8 | function sum(num1,num2){ // num1/num2 就是形参变量(类似于var了一下) 9 | var total = num1 + num2; 10 | total *= 10; 11 | total = total.toFixed(2); 12 | console.log(total) 13 | } 14 | 15 | // 16 | sum(1,2) // -> 30.00 17 | sum(3,4) // -> 70.00 18 | sum(23,41) // -> 640.00 19 | sum(10) // num1 = 10;num2 = undefined; undefined = NaN ; 10 + NaN = NaN; 20 | ``` 21 | ```javascript 22 | // 随便求出两个数的和 23 | function sum(num1,num2){ 24 | // 如果有一个值没有传递的话,为了保证结果不是NaN,我们为其设置一个默认的值: 0; 25 | typeof num1 === "undefined"?num1 = 0: null; // -> num1 = num1 || 0; 26 | typeof num2 === "undefined"?num2 = 0: null; // -> num2 = num2 || 0; 27 | // 容错处理 28 | 29 | var total = num1 + num2; 30 | total *= 10; 31 | total = total.toFixed(2); 32 | console.log(total) 33 | } 34 | 35 | ``` 36 | 37 | ### arguments 实参集合 38 | > 当我们不知道用户具体要传递几个值的时候(传递几个值都行),此时我们无法设置形参的个数,遇到此类需求,需要使用内置的实参集合: arguments 39 | > 1. arguments只有函数才有 40 | > 2. 不管执行函数的时候时候传递实参, arguments天生就存在,没有传递实参arguments是个空集合, 传递了arguments中包含了所有的实参值 41 | > 3. 不管是否设置了形参,arguments中始终存储了所有的实参信息. 42 | 43 | ```javascript 44 | function sum(){ 45 | console.log(arguments); 46 | } 47 | sum(1,2,3) // ->Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ] 48 | ``` 49 | > arguments是一个类数组集合 50 | > 1. 以数字作为索引(属性名), 从零开始 51 | > arguments[0] 第一个实参 52 | > arguments[1] 第二个实参 53 | > ... 54 | > 2. 有一个length的属性,存储的是当前集合的长度(当前传递的实参个数) 55 | > arguments.length 56 | > arguments['length'] 57 | > 58 | > arguments.callee: 存储的是当前函数本身 59 | > arguments.callee.caller: 存储的是当前函数在哪执行的(宿主本身),在全局环境下执行的,结果是: null 60 | 61 | ```javascript 62 | "use strict" // 开启严格模式 63 | function sum(){ 64 | console.log(arguments.callee) 65 | // Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them 66 | } 67 | sum() 68 | 69 | // arguments.callee或者arguments.callee.caller一般真正的项目中很少使用,因为在js严格模式下,或报错 70 | ``` 71 | ```javascript 72 | function sum(){ 73 | var total = null; 74 | for (var i = 0; i < arguments.length; i++) { 75 | var cur = arguments[i]; // 每一轮循环获取当前传递的那个实参值 76 | // 为了防止字符串+数字是字符串拼接不是数学累加,我们最好把其他数据类型首先转换为number类型 77 | cur = Number(cur); 78 | if(isNaN(cur) === false){ 79 | total += cur; 80 | } 81 | } 82 | console.log(total); 83 | } 84 | sum(10,20); 85 | sum(); 86 | sum(10,20,'30'); 87 | sum(10,20,'30','lelei'); 88 | ``` 89 | ```javascript 90 | function sum(){ 91 | var total = null; 92 | for (var i = 0; i < arguments.length; i++) { 93 | var cur = Number(arguments[i]); 94 | !isNaN(cur)?total += cur:null; 95 | } 96 | console.log(total); 97 | } 98 | sum(10,20); 99 | sum(); 100 | sum(10,20,'30'); 101 | sum(10,20,'30','lelei'); 102 | ``` 103 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十三之原型链模式基础.md: -------------------------------------------------------------------------------- 1 | #### 原型链模式 2 | 3 | ```javascript 4 | // 构造函数模式 5 | function CreateJsPerson(name,age){ 6 | this.name = name; 7 | this.age = age; 8 | this.writeJs = function(){ 9 | console.log("my name is " + this.name + ",I can write js!") 10 | } 11 | } 12 | var p1 = new CreateJsPerson("lilei",18); 13 | var p2 = new CreateJsPerson("hanmeimei",16); 14 | console.log(p1.writeJs === p2.writeJs); // false 15 | ``` 16 | > 构造函数模式中拥有了类和实例的概念, 并且实例和实例之间是相互独立开的, -> 实例识别 17 | 18 | ```javascript 19 | function CreateJsPerson(name,age){ 20 | this.name = name; 21 | this.age = age; 22 | } 23 | CreateJsPerson.prototype.writeJs = function(){ 24 | console.log("my name is " + this.name + ",I can write js!") 25 | } 26 | var p1 = new CreateJsPerson("lilei",18); 27 | var p2 = new CreateJsPerson("hanmeimei",16); 28 | console.log(p1.writeJs === p2.writeJs); // -> true 29 | ``` 30 | > 基于构造函数模式的原型模式解决了 方法或者属性公有的问题 -> 把实例之间相同的属性和方法提取成公有的属性和方法 -> 想让谁公有就把它放在CreateJsPerson.prototype上即可 31 | 32 | 33 | 1. 每一个函数数据类型(普通函数,类)都有一个天生自带的属性: prototype(原型), 并且这个属性是一个对象数据类型的值; 34 | 2. 并且在prototype上浏览器天生给它加了一个属性constructor(构造函数), 属性值是当前函数(类)本身 35 | 3. 每一个对象数据类型(普通的对象, 实例, prototype...), 也天生自带一个属性: __ proto__ , 属性值是当前实例所属类的原型(prototype) 36 | 37 | 38 | ```javascript 39 | function Fn(){ 40 | this.x = 100; 41 | } 42 | Fn.prototype.getX = function(){ 43 | console.log(this.x); 44 | }; 45 | var f1 = new Fn; 46 | var f2 = new Fn; 47 | console.log(Fn.prototype.constructor === Fn) // -> true 48 | ``` 49 | 50 | ##### Object是JS中所有对象数据类型的基类(最顶层的类) 51 | > 1. f1 instanceof Object -> true 因为f1通过 __ proto__可以向上级查找,不管有多少级, 最后总能找到Object 52 | > 2. 在Object.prototype上没有 __ proto__这个属性 53 | > 3. f1.hasOwnProperty("x"); // hasOwnProperty是f1的一个属性 54 | > 但我们发现在f1的私有属性上并没有这个方法, 那么如何处理的呢? 55 | > 1). 通过 `对象名.属性名` 的方式获取属性值的时候, 首先在对象的私有的属性上进行查找: 56 | > ->如果私有属性中存在这个属性, 则获取的是私有的属性值; 57 | > ->如果私有的没有, 则通过__ proto__找到所属类的原型(类的原型上定义的属性和方法都是当前实例的属性和方法), 原型上存在的话获取的是公有的属性值; 58 | > ->如果原型上也没有, 则继续通过原型上的 __ proto__继续向上查找, 一直找到Object.prototype为止... 59 | > ->如果都没有,则 undefined 60 | > **这种查找机制就是我们的`原型链模式`** 61 | 62 | ```javascript 63 | console.log(f1.getX === f2.getX) // -> true 64 | console.log(f1.__proto__.getX === f2.getX) // -> true 65 | console.log(f1.getX === Fn.prototype.getX) // -> true 66 | ``` 67 | ```javascript 68 | function Fn(){ 69 | this.x = 100; 70 | this.sum = function(){ 71 | 72 | } 73 | } 74 | Fn.prototype.getX = function(){ 75 | console.log(this.x); 76 | }; 77 | Fn.prototype.sum = function(){ 78 | }; 79 | var f1 = new Fn; 80 | var f2 = new Fn; 81 | console.log(f1.sum === f2.__proto__.sum) // -> false 82 | console.log(f1.sum === f2.prototype.sum) // -> false 83 | ``` 84 | > 在ie浏览器中, 我们原型模式也是同样的原理, 但是浏览器怕你通过 __ proto__ 把公有的修改, 禁止我们使用 __ proto__ 85 | 86 | ```javascript 87 | f1.sum = function(){ 88 | // 修改自己私有的sum 89 | } 90 | f1.__proto__.sum = function(){ 91 | // 修改所属类原型上的sum 92 | } 93 | f1.prototype.sum = function(){ 94 | // 修改所属类原型上的sum 95 | } 96 | ``` 97 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十一之数据类型转换.md: -------------------------------------------------------------------------------- 1 | ### 数据类型转换 2 | 3 | #### 把其他数据类型转换为number 4 | > isNaN , Number , parseInt , parseFloat 5 | > 在进行加减乘除数学运算的时候 6 | 7 | ```javascript 8 | // true -> 1 9 | // false -> 0 10 | 11 | // null -> 0 12 | // undefined -> NaN 13 | 14 | // "" -> 0 15 | // "12" -> 12 16 | // "12px" -> NaN/12 17 | // "lilei" -> NaN 18 | // {} -> NaN 19 | // function() -> NaN 20 | // /^$/ -> NaN 21 | // [] -> "" -> 0 22 | // [12] -> "12" -> 12 23 | // [12,23] -> "12,23" -> NaN/12 24 | 25 | // 引用数据类型转换为数字 26 | // 通过toString方法把数组转化为字符串,然后再调用Number把字符串转换为数字 27 | ``` 28 | 29 | **`js中的数学运算`** 30 | > `+ - * / `加减乘除 31 | > 除了加法有特殊性,其他的运算符都是数学运算,也就是遇到非数字类型,需要把其他转换为number在进行运算 32 | > *加法的特殊性: * 33 | > 在遇到字符串的时候 , `+` 不是数学运算 , 而是字符串拼接 , 只要不遇到字符串就是数学运算 34 | 35 | ```javascript 36 | // 减 乘 除 37 | // 1 -'1' -> 0 38 | // 10 * null -> 0 39 | // 10 / undefined -> NaN 40 | // 10 * [10] -> 100 41 | 42 | // 加 43 | // 1 + "1" -> "11" 44 | // null + "1" -> "null1" 45 | 46 | // 字符串拼接: 是把其他的值转换为字符串然后再拼接(toString) 47 | // 其他数据类型的toString是直接的把值用单(双)引号包起来即可,只有对象的有特殊性,对象.toString() === "[object Object]" 48 | 49 | // 练习 50 | // 1+null+true+undefined+[]+'lilei'+null+undefined+[]+10 51 | 52 | /* 1 + null -> 1 53 | * 1 + true -> 2 54 | * 2 + undefined -> NaN 55 | * NaN + [] -> NaN + "" -> "NaN" 56 | * "NaN" + "lilei" -> "NaNlilei" 57 | * ... 58 | * "NaNlileinullundefined10" 59 | / 60 | ``` 61 | 62 | #### 把其他类型转换为布尔类型 63 | > Boolean , ! , !! 64 | > 在条件判断的时候,也是转换为布尔类型,然后验证条件的真假 65 | > 66 | > 只有`0 , NaN , 空字符串 , null , undefined `五个转换为false,其余的都是转换为true 67 | 68 | ```javascript 69 | // [] -> true 70 | // -1 -> true 71 | 72 | if(box){ 73 | // -> 首先把box变量存储的值获取到,转换为布尔类型,如果为true条件成立,反之不成立 74 | } 75 | 76 | if(3 + "3px"){ // "33px" 77 | // -> 条件成立 78 | } 79 | 80 | if(3 - "3px"){ // NaN 81 | // -> 条件不成立 82 | } 83 | ``` 84 | **`在使用 == 进行比较的时候`** 85 | > 在使用 `==` 进行比较的时候,如果左右两边的数据类型不相同,浏览器会默认转换为相同的类型,然后再比较(`===`不会这样操作) 86 | 87 | ```javascript 88 | // -> 对象和对象: 比较的是空间地址,不是相同的空间,结果肯定是false 89 | // [] == [] -> false 90 | // var a = {}; 91 | // var b = a; 92 | // a == b -> true 93 | 94 | // -> 对象和数字: 把对象转换为数字 95 | // [] == 0 -> true 96 | // ({}) == NaN -> false NaN和自己不相等,和其他任何值都不相等 97 | 98 | // -> 对象和字符串: 把两边都转换为数字比较的 99 | // [] == "" -> true 100 | 101 | // -> 对象和布尔: 把两边都转换为数字 102 | // [] == true -> 0 == 1 -> false 103 | // [] == false -> 0 == 0 -> true 104 | // ![] == false -> true -> ![] 把数组变为布尔再取反 = false , false == false -> true 105 | 106 | // -> 字符串和数字: 字符串转换为数字 107 | 108 | // -> 字符串和布尔: 都转换为数字 109 | 110 | // -> 布尔和数字: 布尔转换为数字 111 | ``` 112 | #### `规律: 两个等于号比较,左右两边数据值的类型不一样,浏览器会把两边的类型都转换为数字然后再比较,但是null和undefined除外` 113 | > null == undefined -> true 114 | > null === undefined -> false 115 | > 116 | > null以及undefined和其他任何值都不相等 117 | > - null == 0 -> false 118 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十之Array数组的查询,拼接,转字符串,排列(序).md: -------------------------------------------------------------------------------- 1 | #### 数组查询 2 | 3 | - slice 4 | 5 | > 数组的查询 6 | > 参数: slice(n,m) 从索引n开始找到索引m处(不包含m) 7 | > 返回值: 把找到的部分以一个新数组返回 8 | > 原来数组不变 9 | > 1. slice(n) 从索引n找到末尾 10 | > 2. slice(0)或slice() 数组克隆,克隆一份和原来数组一模一样的新数组 11 | > 3. slice()支持负数索引,如果传递的索引为负数,浏览器解析的时候按照 总长度+负数索引来处理的 12 | 13 | ```javascript 14 | var ary = [12,23,34,45,56,67,78,89,90]; 15 | var ary1 = ary.slice(3,8) 16 | console.log(ary) // -> [12, 23, 34, 45, 56, 67, 78, 89, 90] 17 | console.log(ary1) // -> [45, 56, 67, 78, 89] 18 | ``` 19 | 20 | #### 数组拼接 21 | 22 | - concat 23 | 24 | > 将多个数组拼接在一起 25 | > 参数: 要拼接的内容(把要拼接的数组放在原数组后面),可以是一个数组,也可以是一些数据值 26 | > 返回值: 拼接后的新数组 27 | > 原数组不改变 28 | > concat() 什么都不拼接相当于把 原数组克隆一个一模一样的新数组 29 | 30 | ```javascript 31 | var ary = [12,23,34] 32 | ary.concat([45,56],'lilei') // -> [12, 23, 34, 45, 56, "lilei"] 33 | console.log(ary) // -> [12, 23, 34] 34 | ``` 35 | 36 | #### 数组转换为字符串 37 | 38 | - toString 39 | 40 | > 把数组转换为字符串(转换后的字符串以逗号分隔每一项) 41 | > 参数: 无 42 | > 返回值: 转换的字符串 43 | > 原有数组不变 44 | 45 | ```javascript 46 | var ary = [12,23,34]; 47 | ary.toString() // -> "12,23,34" 48 | console.log(ary) // -> [12, 23, 34] 49 | ``` 50 | 51 | - join 52 | 53 | > 把数组按照指定的分割符转换为字符串,和字符串中的split相对应 54 | > 参数: 指定的连接符 55 | > 返回值: 连接后的字符串 56 | > 原数组不变 57 | 58 | ```javascript 59 | var ary = [12,23,34]; 60 | ary.join(" ") // -> "12 23 34" 61 | ary.join("+") // -> "12+23+34" 62 | console.log(ary) // -> [12,23,34] 63 | ``` 64 | ```javascript 65 | // 一直数组中的每一项, 想实现数组求和 66 | // 1. 利用循环 67 | var total = 0; 68 | for(var i=0;i 把字符串变为js表达式执行 74 | 75 | ``` 76 | #### 实现数组中的每一项的排序和排列 77 | 78 | - reverse 79 | 80 | > 把数组中的每一项倒过来排列 81 | > 参数: 无 82 | > 返回值: 排列后的新数组 83 | > 原来数组改变 84 | 85 | ```javascript 86 | var ary = [1,23,2,34,21]; 87 | ary.reverse(); // -> [21, 34, 2, 23, 1] 88 | console.log(ary) // -> [21, 34, 2, 23, 1] 89 | ``` 90 | 91 | - sort 92 | 93 | > 实现数组的排序 94 | > 参数: 无或者回调函数 95 | > 返回值: 排序后的数组 96 | > 原有数组改变 97 | > 98 | > 不传参数的情况下,可以给10以内的数字进行升序排列, 但是超过10的就无法处理了(多位数只识别第一位) 99 | 100 | ```javascript 101 | var ary = [1,23,2,34,21]; 102 | ary.sort(); // -> [1, 2, 21, 23, 34] 103 | console.log(ary) // -> [1, 2, 21, 23, 34] 104 | 105 | var ary = [1,23,2,34,21,12]; 106 | ary.sort(); // -> [1, 12, 2, 21, 23, 34] 107 | // -> 12 排在了2的前面,说明sort并不是按数字大小排序,而是只看数字第一位 108 | console.log(ary) // -> [1, 12, 2, 21, 23, 34] 109 | 110 | // -> 从小到大排序 111 | var ary = [1,23,2,34,21,12]; 112 | ary.sort(function(a,b){return a-b}); // -> [1, 2, 12, 21, 23, 34] 113 | // -> 12 排在了2的前面,说明sort并不是按数字大小排序,而是只看数字第一位 114 | console.log(ary) // -> [1, 2, 12, 21, 23, 34] 115 | 116 | // -> 从大到小排序 117 | var ary = [1,23,2,34,21,12]; 118 | ary.sort(function(a,b){return b-a}); // -> [34, 23, 21, 12, 2, 1] 119 | // -> 12 排在了2的前面,说明sort并不是按数字大小排序,而是只看数字第一位 120 | console.log(ary) // -> [34, 23, 21, 12, 2, 1] 121 | ``` 122 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十八之正则表达式(4).md: -------------------------------------------------------------------------------- 1 | #### 正则分组匹配 2 | 3 | 1. 改变优先级 4 | 2. 分组引用 5 | 6 | ` \1 ` 代表和第一个分组出现一模一样的内容; 7 | ` \2 ` 代表和第二个分组出现一模一样的内容; 8 | 9 | ```javascript 10 | var reg = /^(\w)\1(\w)\2$/; 11 | console.log(reg.test("zafq")) // -> false; 12 | console.log(reg.test("zzff")) // -> true; 13 | // 一模一样; 14 | ``` 15 | 3. 分组捕获 -> 正则在捕获的时候,不仅仅把大正则匹配的内容捕获到,而且还可以吧小分组匹配到的内容捕获到 16 | 17 | > ` ?: ` 在分组中代表只匹配不捕获 18 | 19 | ```javascript 20 | var reg = /^(\d{2})(\d{4})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X)$/; 21 | var str = "110105189801015474"; 22 | var ary = reg.exec(str) 23 | console.log(ary); // -> ["110105189801015474", "11", "0105", "1898", "01", "01", "54", "7", "4", index: 0, input: "110105189801015474", groups: undefined] 24 | 25 | // ary[0] -> 大正则匹配的内容 26 | // ary[1] -> 第一分组捕获的内容 27 | // ary[2] -> 第二分组捕获的内容 28 | // ... 29 | ``` 30 | 31 | > ` ?: ` 在分组中代表只匹配不捕获 32 | 33 | ```javascript 34 | var reg = /^(\d{2})(\d{4})(\d{4})(\d{2})(\d{2})(?:\d{2})(\d)(?:\d|X)$/; 35 | var str = "110105189801015474"; 36 | var ary = reg.exec(str) 37 | console.log(ary); // -> ["110105189801015474", "11", "0105", "1898", "01", "01", "7", index: 0, input: "110105189801015474", groups: undefined] 38 | ``` 39 | 40 | #### replace 41 | 把原来的字符串替换为新的字符串 42 | 在不使用正则的情况下,每次执行一次只能替换一个字符 43 | 44 | ```javascript 45 | var str = "lilei18lilei17"; 46 | str.replace("lilei","lileihanmeimei") // -> lileihanmeimei18lilei17 47 | str.replace("lilei","lileihanmeimei").replace("lilei","lileihanmeimei") // -> lileihanmeimeihanmeimei18lilei17 48 | ``` 49 | ```javascript 50 | var str = "lilei18lilei17"; 51 | str.replace(/lilei/,"lileihanmeimei") // -> lileihanmeimei18lilei17 52 | str.replace(/lilei/g,"lileihanmeimei") // -> lileihanmeimei18lileihanmeimei17 53 | ``` 54 | 55 | 关于replace第一项的值是一个正则它的实现原理 56 | 57 | 首相我们和exec捕获一样, 把所有和我们正则匹配的都捕获到,然后把捕获的内容替换成我们需要替换的新内容 58 | /lilei/g 按照这个正则把str中所有可以匹配的都捕获到,然后统一都替换成我们的"lileihanmeimei" 59 | 60 | ```javascript 61 | var str = "lilei18lilei17"; 62 | str = str.replace(/lilei/g,function(){ 63 | console.log(arguments); 64 | // 第一次执行匿名函数的结果 ["lilei", 0, "lilei18lilei17", callee: ƒ, Symbol(Symbol.iterator): ƒ] 65 | // 第二次执行匿名函数的结果 ["lilei", 7, "lilei18lilei17", callee: ƒ, Symbol(Symbol.iterator): ƒ] 66 | return "lileihanmeimei"; 67 | }) 68 | console.log(str) // lileihanmeimei18lileihanmeimei17 69 | ``` 70 | 71 | 第二个参数换成一个函数 72 | 1. 匿名函数执行多少次,取决于正则能在字符串中捕获多少次 - > 正则捕获两次, 所以我们的匿名函数也执行两次 73 | 2. 每一次执行匿名函数, 里面传递的参数值arguments和我们自己通过exec捕获到的结果是非常类似的(即使正则有分组, 我们同样可以通过arguments获取到分组捕获的内容) 74 | 3. return 返回的结果是啥就相当于把当前这一次大正则捕获的内容替换成你返回的内容 75 | 76 | 77 | ```javascript 78 | var str = "lilei18lilei17"; 79 | str = str.replace(/\d+/g, function(){ 80 | console.log(arguments[1]) 81 | return 20; 82 | }) 83 | console.log(str) // lilei20lilei20 84 | 85 | // RegExp.$1 -> 获取第一个分组捕获的内容 86 | ``` 87 | 88 | ```javascript 89 | var str = "20180614"; // 贰零壹捌零陆壹肆 90 | var ary = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"]; 91 | str = str.replace(/\d/g, function(){ 92 | // var num = arguments[0]; 93 | // var str = ary[num]; 94 | // return str; 95 | 96 | return ary[arguments[0]]; // 简写 97 | }); 98 | console.log(str); // 贰零壹捌零陆壹肆 99 | ``` 100 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记八之if-else if-else判断语句,三元运算符,switch case判断语句.md: -------------------------------------------------------------------------------- 1 | ### 判断操作语句 2 | 3 | ```javascript 4 | if(条件1){ 5 | // 条件1成立要执行的操作 6 | }else if(条件2){ 7 | // 条件1不成立,条件2成立,执行的操作 8 | } 9 | ... 10 | else{ 11 | // 以上条件都不成立 12 | } 13 | 14 | // 如果好几个条件都成立了,只把第一个成立的条件执行,后面成立的条件忽略不管 15 | 16 | //条件: a == b a >= b a <= b ... 17 | 18 | if(a){ 19 | // 先把a转换为布尔类型,判断真假一次来决定条件是否成立 20 | } 21 | ``` 22 | 23 | > && 并 24 | > || 或 25 | 26 | 27 | ```javascript 28 | var num = parseFloat('width:12.5px;'); // -> NaN 29 | 30 | if(num == 12.5){ // NaN != 12.5 31 | alert(12.5); 32 | }else if(num == NaN){ //NaN != NaN 33 | alert(NaN) 34 | }else if(typeof num == 'number'){ // typeof NaN -> 'number' == 'number' 35 | alert(0) // -> '0' 36 | }else{ 37 | alert('啥也不是') 38 | } 39 | 40 | ``` 41 | 42 | ### 三元运算符 43 | 44 | **`条件?条件成立执行:条件不成立执行`** 45 | ```javascript 46 | var num = 10; 47 | if(num > 5 && num < 10){ 48 | num ++; 49 | }else{ 50 | num --; 51 | } 52 | // 改写成三元运算符 53 | num > 5 && num < 10 ? num ++ : num --; 54 | ``` 55 | 56 | ```javascript 57 | var num = 10; 58 | if(num > 5 && num < 10){ 59 | num ++; 60 | } 61 | // 改写成三元运算符 62 | num > 5 && num < 10 ? num ++ : null ; 63 | // 如果条件成立或不成立的某一种情况并不需要做什么处理,我们空着语法不符合 64 | // 我们使用null/undefined/void 0 占位即可 65 | ``` 66 | 67 | ```javascript 68 | var num = 10; 69 | if(num > 5 && num < 10){ 70 | num ++; 71 | console.log(num) 72 | } 73 | // 改写成三元运算符 74 | // 某一种情况执行多条操作,使用小括号包起来,中间用逗号分隔 75 | num > 5 && num < 10 ? (num ++,console.log(num)): null ; 76 | ``` 77 | **`在三元运算符的操作中不能出现break/continue/return这些关键词,我们无法用三元运算符代替if else`** 78 | 79 | ### switch case 80 | 81 | > switch case应用于if-else中一个变量在不同值情况下的不同操作 82 | 83 | ```javascript 84 | var num = 10; 85 | switch(num){ 86 | // switch后面小括号中存放的是一个值(一般我们都写变量: 把变量存储的值拿来用,有时候也可能是一个计算) 87 | case 1: 88 | // case 后面放入的都是值,目的是验证switch后面的值和哪一个case后面的值相等,相等的进行对应的处理 89 | ... 90 | break; 91 | // 每一个case结束后都要加break,结束当前的判断 92 | case 10: 93 | ... 94 | break 95 | default: 96 | // switch 后面的值和每一个case情况对应的值都不相等,执行最后的default,类似于else 97 | ... 98 | } 99 | ``` 100 | 101 | ```javascript 102 | var num = 5; 103 | 104 | // num%2 让num存储的值除以2取余数(0或1) 105 | switch(num%2){ 106 | // 先把取余操作进行运算,那运算结果和case比较 107 | case 0: 108 | num++; 109 | break; 110 | case 2-1: 111 | // case 后面也应该是值,此处先把2-1计算,把计算结果和switch值比较 112 | num--; 113 | // break; 114 | // 最后一项可以不加break,不加也能跳出判断 115 | } 116 | num // -> 4 117 | ``` 118 | 119 | ```javascript 120 | var num = 6; 121 | switch(num%3){ 122 | case 0: 123 | num++; 124 | // 不加break,不管后面的条件是否成立,都会继续向下执行,直到遇到break为止; 125 | case 1: 126 | num--; 127 | break; 128 | case 2: 129 | num = 0; 130 | break; 131 | } 132 | num // -> 6 133 | ``` 134 | 135 | **`小应用`** 136 | > 把符合某几项值都去做同一件事情,使用不加break实现 137 | 138 | ```javascript 139 | var num = 6; 140 | switch(num%3){ 141 | case 0: 142 | case 1: // 余数是0或1都执行减减的操作 143 | num--; 144 | break; 145 | default: 146 | num = 0; 147 | } 148 | num // -> 5 149 | ``` 150 | 151 | ```javascript 152 | var num = '6'; 153 | switch(num){ 154 | case 6: 155 | num--; 156 | break; 157 | default: 158 | num=0; 159 | } 160 | num // -> 0 161 | 162 | //switch case中的比较是: === 163 | 164 | ``` 165 | 166 | > =: 赋值,等号左边是变量, 右边是值 167 | > ==: 比较, 如果左右两边值的类型不一样,浏览器会默认转换为一样的然后在进行比较 ('6' == 6 -> true) 168 | > ===: 绝对相等, 不仅要求值一样,并且类型也完全一样 ('6' === 6 -> false) 169 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十九之this关键字.md: -------------------------------------------------------------------------------- 1 | 我们在js中主要研究的都是函数中的this 2 | 3 | js中的this代表的是当前行为执行的主体 4 | 5 | js中的context(上下文)代表的是当前行为执行的环境(区域) 6 | 7 | this是谁和函数在哪定义的和在哪执行的都没有任何的关系 8 | 9 | #### 如何的区分 this 10 | 11 | **1.函数执行,首先看函数名前面是否有 " `.` ",有的话" `.` "前面是谁this就是谁;没有的话this就是window;** 12 | 13 | ```javascript 14 | function fn(){ 15 | console.log(this) 16 | } 17 | 18 | var obj = { fn : fn }; 19 | 20 | fn(); // this -> window 21 | 22 | obj.fn() // this -> obj 23 | 24 | function sum(){ 25 | fn(); // this -> window 26 | } 27 | sum() 28 | 29 | var oo = { 30 | function sum(){ 31 | fn(); //this -> window 32 | } 33 | } 34 | 35 | oo.sum(); 36 | ``` 37 | 38 | **2.自执行函数中的this永远是window** 39 | 40 | **3.给元素的某一个事件绑定方法,当事件触发的时候,执行对应的方法** 41 | 42 | ```html 43 |
点击
44 | 53 | ``` 54 | 55 | #### 预解释/作用域/内存/this综合练习题 56 | 57 | ```javascript 58 | var num = 20; 59 | var obj = { 60 | num: 30, 61 | fn: (function(num){ 62 | this.num *= 3; 63 | num += 15; 64 | var num = 45; 65 | return function(){ 66 | this.num *= 4; 67 | num += 20; 68 | console.log(num); 69 | } 70 | })(num) // -> 把全局变量num的值20赋值给了自执行函数的形参,而不是obj下的30,如果想是obj下的30,我们需要写obj.num 71 | }; 72 | var fn = obj.fn; 73 | fn(); // -> 65 74 | obj.fn(); // -> 85 75 | console.log(window.num, obj.num); // -> 240, 120 76 | ``` 77 | 78 | 79 | 练习: 累加的投票器 80 | 81 | ```html 82 | 86 |
请投票: 0
87 | ``` 88 | 89 | 方案一: 利用全局作用域不销毁的原理, 把需要累加的数字定义为全局的变量; 90 | 91 | ```javascript 92 | var oBtn = document.getElementById('btn'), 93 | spanNum = document.getElementById('spanNum'); 94 | 95 | // 方案一 96 | var count = 0 97 | oBtn.onclick = function (){ 98 | count++; 99 | spanNum.innerHTML = count; 100 | } // 弊端: 在项目中为了防止全局变量之间的冲突,我们一般是禁止或者减少使用全局变量的 101 | ``` 102 | 103 | 方案二: 自己形成一个不销毁的私有作用域来保护需要累加的数字 104 | 105 | ```javascript 106 | // 方案二(1) 107 | var oBtn = document.getElementById('btn'), 108 | spanNum = document.getElementById('spanNum'); 109 | ~function(){ 110 | var count = 0 111 | oBtn.onclick = function (){ 112 | count++; 113 | spanNum.innerHTML = count; 114 | } 115 | }() // 弊端: 有一个不销毁的私有作用域,所以占内存 116 | ``` 117 | ```javascript 118 | // 方案二(2) 119 | var oBtn = document.getElementById('btn'), 120 | spanNum = document.getElementById('spanNum'); 121 | oBtn.onclick = (function(){ 122 | var count = 0 123 | return function(){ 124 | count++; 125 | spanNum.innerHTML = count; 126 | } 127 | })() // 弊端: 有一个不销毁的私有作用域,所以占内存 128 | ``` 129 | 130 | 方案三: 利用innerHTML的方式处理: 每一次点击的时候先到页面中获取最新的值,然后累加,最后把累加的结果重新放回去 131 | 132 | ```javascript 133 | // 方案三 134 | var oBtn = document.getElementById('btn'), 135 | spanNum = document.getElementById('spanNum'); 136 | 137 | oBtn.onclick = function(){ 138 | spanNum.innerHTML++; 139 | } // 弊端: 每一次都需要把页面中的内容先转换为字符串然后累加, 140 | // 累加完再重新添加回去,当重新添加的时候浏览器都要重新渲染一次 141 | ``` 142 | 143 | 方案四: 利用自定义属性存储(推荐) 144 | 145 | ```javascript 146 | oBtn.count = 0; 147 | oBtn.onclick = function(){ 148 | sapnNum.innerHTML = ++this.count 149 | } 150 | ``` 151 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十二之构造函数模式扩展.md: -------------------------------------------------------------------------------- 1 | #### 构造函数模式扩展 2 | 3 | ```javascript 4 | function Fn(){ 5 | 6 | } 7 | Fn(); // -> 普通函数执行 8 | new Fn(); // -> 构造函数执行 9 | var f1 = new Fn(); // -> f1是构造函数的一个实例 10 | ``` 11 | 12 | 1. 在构造函数模式中new Fn()执行, 如果不需要传参, 后面的小括号可以省略: new Fn 13 | 14 | ```javascript 15 | var f1 = new Fn; 16 | ``` 17 | 18 | 2. this的问题: 在类中出现的 this.xxx=xxx 中的this都是当前类的实例, 而某一个属性值(方法), 方法中的this需要看方法执行的时候, 前面是否有`.`才知道this是谁 19 | 20 | ```javascript 21 | function Fn(){ 22 | // this -> f1 23 | this.num = 100; 24 | this.getNum = function(){ 25 | // this -> 需要看getNum执行的时候才知道 26 | console.log(this.num) 27 | } 28 | } 29 | var f1 = new Fn; 30 | f1.getNum(); // 100 -> 此时的getNum函数的this是f1,f1.num = 100; 31 | var q = f1.getNum; 32 | q(); // undefined -> 此时的getNum函数的this是window,而window中并没num,所以... 33 | ``` 34 | 35 | 3. 类有普通函数的一面, 当函数执行的时候, var x其实只是当前形成的私有作用域中的私有变量而已, 它和我们的f1这个实例没有任何的关系,只有 this.xxx=xxx才相当于给f1这个实例增加私有的属性和方法, 才和我们的f1有关系 36 | 37 | ```javascript 38 | function Fn(){ 39 | var x = 10; 40 | this.num = 100; 41 | this.getNum = function(){ 42 | console.log(this.num) 43 | } 44 | } 45 | var f1 = new Fn; 46 | console.log(f1.x) // undefined 47 | ``` 48 | 4. 在构造函数模式中, 浏览器会默认的把我们的实例返回(返回的是一个对象数据类型的值);如果我们自己手动写了return返回: 49 | 1. 返回的是一个基本数据类型的值,当前实例是不变的,例如: return 100; f1还是当前Fn类的实例 50 | 2. 返回的是一个引用数据类型的值, 当前的实例会被自己返回的值给替换掉, 例如: return {name:"lilei"} f1就不再是Fn的实例了,而是对象{name:"lilei"}; 51 | 52 | ```javascript 53 | function Fn(){ 54 | this.num = 100; 55 | this.getNum = function(){ 56 | console.log(this.num) 57 | } 58 | } 59 | var f1 = new Fn; 60 | console.log(f1) // -> Fn {num: 100, getNum: ƒ} 61 | ``` 62 | ```javascript 63 | function Fn(){ 64 | this.num = 100; 65 | this.getNum = function(){ 66 | console.log(this.num) 67 | } 68 | return 100; // 手动返回基本数据类型(值类型) 69 | } 70 | var f1 = new Fn; 71 | console.log(f1) // -> Fn {num: 100, getNum: ƒ} 72 | ``` 73 | ```javascript 74 | function Fn(){ 75 | this.num = 100; 76 | this.getNum = function(){ 77 | console.log(this.num) 78 | } 79 | return {name:"lilei"}; // 手动返回引用数据类型(对象类型) 80 | } 81 | var f1 = new Fn; 82 | console.log(f1) // -> {name: "lilei"} 83 | ``` 84 | 85 | 5. 检测某一个实例是否属于这个类 -> `instanceof` 86 | 87 | ```javascript 88 | function Fn(){ 89 | this.num = 100; 90 | this.getNum = function(){ 91 | console.log(this.num) 92 | } 93 | } 94 | var f1 = new Fn; 95 | console.log(f1 instanceof Fn) // -> true 96 | console.log(f1 instanceof Array) // -> false 97 | console.log(f1 instanceof Object) // -> true 98 | // 因为所有的实例都是对象数据类型 而每一个对象数据类型都是Object这个内置类的一个实例, 所以f1也是他的一个实例 99 | ``` 100 | 101 | > 对于检测数据类型来说, typeof有自己的局限性,不能细分object下的对象,数组,正则... 102 | 103 | ```javascript 104 | var a = []; 105 | console.log(a instanceof Array) // -> true 说明a是一个数组 106 | ``` 107 | 6. f1和f2都是Fn这个类的一个实例, 都拥有num和getNum两个属性, 但是这两个属性是各自的私有属性, 所以: 108 | 109 | ```javascript 110 | function Fn(){ 111 | this.num = 100; 112 | this.getNum = function(){ 113 | console.log(this.num) 114 | } 115 | } 116 | var f1 = new Fn; 117 | var f2 = new Fn; 118 | console.log(f1 === f2) // -> false 119 | console.log(f1.getNum === f2.getNum) // false 120 | ``` 121 | > in: 检测某一个属性是否属于这个对象 (attr in Object) 不管是私有的属性还是公有的属性, 只要存在, 用in检测都是true 122 | 123 | ```javascript 124 | console.log("getNum" in f1) // -> true 125 | ``` 126 | > hasOwnProperty: 用来检测某一个属性是否为这个对象的"私有属性", 这个方法只能检测私有的属性 127 | 128 | ```javascript 129 | console.log(f1.hasOwnProperty('getNum')) // -> true 130 | ``` 131 | > 思考: 检测某一个属性是否为该对象的"公有属性" hasPubProperty 132 | 133 | ```javascript 134 | function hasPubProperty(obj,attr){ 135 | // 首先保证是它的一个属性并且还不是私有属性, 那么只能是公有的属性了 136 | return (attr in obj) && !obj.hasOwnProperty(attr); 137 | } 138 | console.log(hasPubProperty(f1,"getNum")); // -> false 139 | ``` 140 | 7. isPrototypeOf 141 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十五之DOM基础-获取元素的方法.md: -------------------------------------------------------------------------------- 1 | ### DOM基础 2 | 3 | > DOM: document object model 文档对象模型, 4 | > 提供一些属性和方法可以让我们去操作DOM元素 5 | 6 | #### 获取DOM元素的方法 7 | 8 | - `document,getElementById()` 获取一个元素 9 | - `[context].getElementsByTagName()` 获取元素集合 10 | - `[content].getElementsByClassName()` 获取元素集合 11 | - `document.getElementsByName()` 获取节点集合 12 | - `document.documentElement` 获取整个HTML对象 13 | - `document.body` 获取真个body对象 14 | - `document.head` 获取整个head对象 15 | - `[context].querySelector` 获取一个元素对象 16 | - `[content].querySelectorAll` 获取元素集合 17 | - ... 18 | 19 | —— 20 | - **getElementById** 21 | 22 | > 此方法的上下文只能是document 23 | > 一个html页面中元素的id理论上是不能重复的 24 | 25 | > 1. 如果页面中的id重复了,我们只获得页面中的一个元素且是第一个元素 26 | > 2. 在ie7及更低版本浏览器中,会把表单元素的name值当做id来识别使用(项目中尽量 *不要让表单的name和其他元素的id相同* ) 27 | 28 | ```html 29 | 30 |
31 |
32 |
33 | 38 | ``` 39 | > 3. 如果我们把js放在结构下面,我们可以直接使用id值来获取这个元素(不需要通过getElementById获取),而且这种方式会把页面中所有id是它的元素都获取到(元素对象/元素集合) -> `不推荐` 40 | 41 | ```html 42 |
43 |
44 |
45 | 49 | ``` 50 | ```html 51 |
52 |
53 |
54 | 66 | ``` 67 | 68 | - **getElementByTagName** 69 | 70 | > 上下文是可以自己来指定 71 | > 获取到的结果是一个元素集合(类数组集合) 72 | > 73 | > 1. 获取的结果是集合,哪怕集合中只有一项,我们想要操作这一项(元素对象), 需要先从集合中获取出来, 然后再操作 74 | > 2. 在指定的上下文中,获取所有子子孙孙元素中标签名叫做这个的`后代筛选` 75 | 76 | ```html 77 | 78 |
79 |
80 |
81 | 82 | 92 | ``` 93 | 94 | - **getElementsByClassName** 95 | 96 | > 上下文也可以随意指定 97 | > 获取的结果也是一个元素集合(类数组集合) 98 | > 99 | > 1. 真实项目中我们经常会通过样式类名来获取元素,getElementsByClassName这个方法在ie6~8浏览器中是不兼容的 100 | 101 | - **getElementsName** 102 | 103 | > 通过元素的name属性值获取一组元素(类数组: 节点集合NodeList) 104 | > 它的上下文也只能是document 105 | > 106 | > 1. ie浏览器中只能识别表单元素的name属性值,所以我们这个方法一般都是用来操作表单元素的 107 | 108 | - **document.documentElement / document.body** 109 | 110 | > 获取html或者body (一个元素对象) 111 | 112 | ```javascript 113 | document.documentElement.clienWidth || document.body.clienWidth 114 | // -> 获取当前浏览器可视区域的宽度(当前页面一屏幕的宽度) 115 | // -> clienHeight: 获取高度 116 | ``` 117 | 118 | - **querySelector / querySelectorAll** 119 | 120 | > 在ie6~8下不兼容,而且也没有什么特别好办法处理它的兼容,所以这两个方法一般多用于移动端开发使用 121 | > 122 | > querySelector: 获取一个元素对象 123 | > querySelectorAll: 获取的是一个元素集合 124 | > 125 | > 支持大部分css选择器 126 | 127 | ```html 128 |
129 |
130 |
131 | 144 | ``` 145 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十获取数组中的最大值和最小值(四种方法).md: -------------------------------------------------------------------------------- 1 | ##### 获取数组中最大值和最小值 2 | 3 | - 给数组进行排序(小->大), 第一个和最后一个就是最小值和最大值 4 | 5 | ```javascript 6 | // 方案一: 7 | var ary = [12,23,34,46,13,35,11,15] 8 | ary.sort(function(a,b){return a-b;}); 9 | var min = ary[0]; 10 | var max = ary[ary.length-1]; 11 | console.log(min,max) // -> 11 46 12 | ``` 13 | - 使用Math中的max/min方法实现 14 | 15 | ```javascript 16 | // 方案二(1): 17 | // 以下代码不能实现 18 | var ary = [12,23,34,46,13,35,11,15]; 19 | var min = Math.min(ary); 20 | console.log(min); // -> NaN 21 | console.log(Math.min(12,23,34,46,13,35,11,15)) // -> 11 22 | // 它是在执行的时候,把需要比较的值一个个传递进来,这样才可以得到最后的结果 23 | // 直接放入数组进来是不可以的 24 | ``` 25 | - 假设法: 假设当前数组中的第一个值是最大值, 然后拿这个数和后面的想逐个进行比较,如果后面某一个值比假设的还要大,说明假设错了,我们把假设的值替换... 26 | 27 | ```javascript 28 | // 方案三 29 | var ary = [12,23,34,46,13,35,11,15]; 30 | var max=ary[0],min=ary[0]; 31 | for(var i=1;imax?max=cur:null; 34 | cur eval: 把一个字符串变为js表达式执行 40 | 41 | ```javascript 42 | eval("12+23+34+45+56") // 170 43 | ``` 44 | ```javascript 45 | // 方案二(2-1): 46 | // 以下代码不能实现 47 | var ary = [12,23,34,46,13,35,11,15]; 48 | ary.join() // -> "12,23,34,46,13,35,11,15" 49 | ary.toString() // -> "12,23,34,46,13,35,11,15" 50 | eval(ary.toString()) // -> 15 只获取最后一项的值 51 | ``` 52 | 53 | > 括号表达式 54 | 55 | ```javascript 56 | function fn1(){console.log(1)}; 57 | function fn2(){console.log(2)} 58 | ;(fn1,fn2)(); // -> 2 59 | // -> 只有fn2执行了 60 | // -> (x1,x2,x3...)括号表达式, 一个括号中出现多项内容,中间用 "." 隔开, 61 | // 但是我们最后获取到的结果只有最后一项 62 | ``` 63 | ```javascript 64 | function fn1(){console.log(this)}; 65 | function fn2(){console.log(this)} 66 | var obj = {name:"lilei",fn:fn2}; 67 | (fn2,obj.fn)(); // -> window 68 | // 执行的是obj.fn, 但是执行的时候里面的this变为了window而不是obj 69 | ``` 70 | 71 | ```javascript 72 | function fn1(){console.log(this)}; 73 | function fn2(){console.log(this)} 74 | var obj = {name:"lilei",fn:fn2}; 75 | (obj.fn)(); // -> this还是obj 76 | ``` 77 | ```javascript 78 | // 方案二(2-2): 79 | var ary = [12,23,34,46,13,35,11,15]; 80 | var min = eval("Math.min(" + ary.toString() + ")"); 81 | var max = eval("Math.max(" + ary.toString() + ")"); 82 | console.log(min); 83 | console.log(max); 84 | ``` 85 | 86 | ```javascript 87 | // 方案二(2-3): 88 | var ary = [12,23,34,46,13,35,11,15]; 89 | var min = Math.min.apply(null,ary) 90 | var max = Math.max.apply(null,ary) 91 | console.log(min); 92 | console.log(max); 93 | ``` 94 | 95 | ##### 求平均数 96 | 97 | ```javascript 98 | function avg(){ 99 | // arguments.sort(); 100 | // Uncaught TypeError: arguments.sort is not a function 101 | // arguments是一个类数组集合,它不是一个数组,不能直接使用数组方法 102 | 103 | // 1. 将类数组转换为数组 104 | var ary = []; 105 | for(var i=0;i [9.8, 9.7, 10, 9.9, 9, 9.8, 3] 109 | 110 | // 2. 给数组排序,去掉开头和结尾,剩下的书求平均数 111 | ary.sort(function(a,b){return a-b;}) 112 | ary.shift(); 113 | ary.pop(); 114 | return (eval(ary.join("+"))/ary.length).toFixed(2) 115 | } 116 | var res = avg(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0) 117 | console.log(res) // -> 9.64 118 | ``` 119 | 120 | ```javascript 121 | function avg(){ 122 | // 1. 将类数组转换为数组 123 | // 借用数组原型上的slice方法,当slice执行的时候,让方法中的this变为我要处理的arguments,实现将数组arguments转换为数组 124 | var ary = Array.prototype.slice.call(arguments); 125 | 126 | ary.sort(function(a,b){return a-b;}) 127 | ary.shift(); 128 | ary.pop(); 129 | return (eval(ary.join("+"))/ary.length).toFixed(2) 130 | } 131 | var res = avg(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0) 132 | console.log(res) // -> 9.64 133 | ``` 134 | 135 | ```javascript 136 | function avg(){ 137 | Array.prototype.sort.call(arguments,function(a,b){return a-b;}); 138 | [].shift.call(arguments); 139 | [].pop.call(arguments); 140 | return (eval([].join.call(arguments, "+"))/arguments.length).toFixed(2); 141 | } 142 | var res = avg(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0); 143 | console.log(res) // -> 9.64 144 | ``` 145 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十九之Array数组的增删改.md: -------------------------------------------------------------------------------- 1 | ### 数组的基础结构 2 | > 数组也是对象数据类型的 typeOf [] 3 | 4 | ```javascript 5 | console.log(typeOf [])// -> "object" 6 | ``` 7 | > 数组也有属性名,只不过属性名是数字,我们把数字属性名称之为它的索引; 8 | > 数组是以数字作为索引,索引从零开始,有一个length属性代表数组的长度 9 | 10 | ```javascript 11 | // [12,23,34] 12 | // 0: 12 13 | // 1: 23 14 | // 2: 34 15 | // length: 3 16 | ``` 17 | 18 | > 类数组: 类似于数组,但是不是数组 19 | > 1. 通过getElementsByTagName获取的元素集合是类数组; 20 | > 2. 函数中的实参集合arguments也是类数组 21 | > ... 22 | 23 | - 循环数组中的每一项 24 | 25 | ```javascript 26 | // for循环 27 | var ary = [12,23,34,45]; 28 | Array.prototype.aa = 100; 29 | for(var i=0;i 12,23,34,45 31 | } 32 | 33 | // for in循环 34 | for(var key in ary){ 35 | // -> key: 属性名(数组中的属性名是索引) 36 | console.log(ary[key]) // -> 12,23,34,45,100 37 | } 38 | 39 | // -> 区别: for循环只能遍历到数组的私有的一些属性,儿for in循环可以吧一些定义的公共属性也能遍历到 40 | ``` 41 | 42 | #### 数组中的常用方法 43 | 44 | > 数组中有很多常用方法 'console.dir(Array.prototype)' 45 | 46 | - 四个方面记忆数组的方法 47 | 48 | > 1. 方法的意义和作用 49 | > 2. 方法的参数 50 | > 3. 方法的返回值 51 | > 4. 通过此方法,原来的数组是否发生了改变 52 | 53 | - 实现数组的增加,修改,删除 54 | 55 | ##### 增加 56 | 57 | - push() 58 | 59 | > 向数组的末尾增加新内容; 60 | > 参数: 一个或多个,任何数据类型都可以; 想要给数组末尾追加什么,直接传递到push方法中即可,传递多个用逗号隔开 61 | > 返回值: 新增后数组的长度 62 | > 原有数组改变了 63 | 64 | ```javascript 65 | var ary = [12,23,34]; 66 | ary.push(45,{name:'lilei'},function(){}); // -> 6 67 | console.log(ary); // -> [12, 23, 34, 45, {…}, ƒ] 68 | ``` 69 | - unshift() 70 | 71 | > 向数组的开头增加新内容; 72 | > 参数: 一个或多个,任何数据类型都可以;(可以是多个任意数据类型的值) 73 | > 返回值: 新增后数组的长度 74 | > 原有数组改变了 75 | 76 | ```javascript 77 | var ary = [12,23,34] 78 | ary.unshift(45,{name:'lilei'},function(){}); // -> 6 79 | console.log(ary); // -> [45, {…}, ƒ, 12, 23, 34] 80 | ``` 81 | > 把数组当做一个普通对象,使用对象键值对的操作,给其设置新的属性(索引) 82 | > 向数组的末尾添加新的内容 83 | 84 | ```javascript 85 | var ary = [12,23,34]; 86 | ary[ary.length] = 45; 87 | console.log(ary) // -> [12, 23, 34, 45] 88 | ``` 89 | 90 | ##### 删除 91 | 92 | - pop(): 删除数组中的最后一项 93 | 94 | > 参数: 无 95 | > 返回值: 别删除的最后一项 96 | > 原有数组改变 97 | 98 | ```javascript 99 | var ary = [12,23,34]; 100 | ary.pop() 101 | console.log(ary) // -> [12,23] 102 | ``` 103 | 104 | - shift(): 删除数组中的第一项 105 | 106 | > 参数: 无 107 | > 返回值: 被删除的那一项 108 | > 原有数组改变了 109 | > 删除第一项之后, 后面的每一项索引都要向前进一位(导致后面项的索引发生改变) 110 | 111 | ```javascript 112 | var ary = [12,23,34]; 113 | ary.shift() 114 | console.log(ary) // -> [23,34] 115 | ``` 116 | - delete 117 | 118 | > 把数组当做普通的对象操作 119 | > delete ary[索引]; 删除指定索引项 120 | > 当前项被删除后,其他项索引不会改变 121 | > 当前数组的长度也不会改变 122 | 123 | ```javascript 124 | var ary = [12,23,34]; 125 | delete ary[0] 126 | console.log(ary) // -> (3) [empty, 23, 34] 127 | ``` 128 | 129 | - ary.length-- 130 | 131 | > 删除数组最后一项 132 | 133 | ```javascript 134 | var ary = [12,23,34]; 135 | ary.length--; 136 | console.log(ary) // -> [12,23] 137 | ``` 138 | 139 | - splice 140 | 141 | > 数组中内置方法,本意删除,但可以实现数组的增加/修改/删除 142 | > 143 | > splice(n,m): 从索引n开始,删除m个(m不写是删除到数组的末尾,) 144 | > 返回值: 被删除的内容的新数组 145 | > 原有数组改变 146 | 147 | ```javascript 148 | var ary = [12,23,34]; 149 | ary.splice(1,2); // 返回:[23,34] 150 | console.log(ary) // -> 12 151 | ``` 152 | 153 | > splice(0): 清空数组 154 | 155 | ```javascript 156 | var ary = [12,23,34]; 157 | ary.splice(0); 158 | console.log(ary) // -> [] 159 | ``` 160 | 161 | > splice(): 一项也不删,返回一个空数组 162 | 163 | ```javascript 164 | var ary = [12,23,34]; 165 | ary.splice(); 166 | console.log(ary) // -> [12, 23, 34] 167 | ``` 168 | 169 | > splice实现修改 170 | > splice(n,m,x): 在原有删除的基础上用x代替原有项 171 | 172 | ```javascript 173 | var ary = [12,23,34]; 174 | ary.splice(1,1,45); 175 | console.log(ary) // -> [12, 45, 34] 176 | ``` 177 | 178 | > splice实现增加 179 | > splice(n,0,x): 在修改的基础上,一项都不删除,把x插入到索引n的前面 180 | > splice(0,0,x): 向数组开头增加新内容 181 | > splice(ary.length,0,x): 向数组末尾增加新内容 182 | > splice(0,1): 删除数组第一项 183 | > splice(ary.length-1): 删除数组最后一项 184 | 185 | ```javascript 186 | var ary = [12,23,34]; 187 | ary.splice(1,0,45); 188 | console.log(ary); // -> [12, 45, 23, 34] 189 | ary.splice(0,0,56); 190 | console.log(ary); // -> [56, 12, 45, 23, 34] 191 | ``` 192 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记五十之数据类型检测.md: -------------------------------------------------------------------------------- 1 | #### 数据类型检测 2 | 3 | 1. `typeof` 用来检测数据类型的运算符 4 | 5 | ```javascript 6 | console.log(typeof 12); // -> "number" 7 | var str = "lilei"; 8 | console.log(typeof str); // -> "string" 9 | console.log(typeof null); // -> "object" 10 | 11 | console.log(typeof typeof typeof function(){}) // -> "string" 12 | ``` 13 | > 使用typeof检测数据类型, 首先返回的都是一个字符串其次字符串中包含了对应的数据类型 14 | > `"number"`, `"string"`, `"boolean"`,`"object"`, `"function"`, `"undefined"` 15 | > `局限性:` 不能具体的细分是数组,正则,或对象中的其他的值,因为使用typeof检测数据类型, 对于对象数据类型中的所有的值,最后返回的都是"object"; 16 | 17 | ```javascript 18 | // 定义形参不传值,默认"undefined" 19 | function fn(num1,num2){ 20 | if(typeof num2 === "undefined"){ 21 | num2 = 0; 22 | } 23 | } 24 | fn(10); 25 | 26 | 27 | // 回调函数执行 28 | function fn(callback){ 29 | typeof callback === "function"?callback():null; 30 | 31 | // callback && callback(); 32 | } 33 | fn(function(){ 34 | 35 | }) 36 | ``` 37 | --- 38 | 39 | 2. `instanceof` 检测某一个实例是否属于某个类 40 | 41 | ```javascript 42 | var obj = [12,23]; 43 | console.log(obj instanceof Array); // -> true 44 | console.log(obj instanceof RegExp); // -> false 45 | ``` 46 | ```javascript 47 | console.log(1 instanceof Number); // -> false 48 | console.log(new Number(1) instanceof Number); // -> true 49 | ``` 50 | > 1. 不能用来检测和处理字面量方式创建出来的基本数据类型的值 51 | > `局限性: `对于基本数据类型来说,字面量方式创建出来的结果和实例方式创建出来的结果是有一定的区别的, 从严格意义上来讲, 只有实例创建出来的结果才是标准的对象数据类型, 也是标准的Number这个类额一个实例; 对于字面量方式创建出来的结果是基本数据类型值,不是严谨的实例,但是由于js的松散特点,导致了可以使用Number.prototype上提供的方法; 52 | 53 | ```javascript 54 | var ary = []; 55 | console.log(ary instanceof Array); // -> true 56 | console.log(ary instanceof Object); // -> true 57 | function fn(){}; 58 | console.log(fn instanceof Function); // -> true 59 | console.log(fn instanceof Object); // -> true 60 | ``` 61 | 62 | > 2. instanceof的特性: 只要在当前实例的原型链上,我们用其检测出来的结果都是true 63 | 64 | ![instanceof](http://img.uplyw.com/note/20180621230925.png) 65 | --- 66 | 67 | 3. `constructor` 构造函数 作用和instanceof非常相似 68 | 69 | ```javascript 70 | var obj = []; 71 | console.log(obj.constructor === Array) // -> true 72 | console.log(obj.constructor === RegExp) // -> false 73 | var num = 1; 74 | console.log(num.constructor === Number) // -> true 75 | // constructor能够处理基本数据类型的检测 76 | // constructor检测Object和instanceof不一样, 一般情况下是检测不了的 77 | var reg = /^$/; 78 | console.log(reg.constructor === RegExp) // -> true 79 | console.log(reg.constructor === Object) // -> false 80 | ``` 81 | > `局限性: `我们可以把类的原型进行重写, 在重写的过程中很有可能出现把之前的constructor给覆盖了, 这样检测出来的结果就是不准确的 82 | > 对于特殊的数据类型null和undefined, 她们的所属类是Null和Undefined, 但是浏览器把这两个类保护起来了, 不允许我们在外面访问使用 83 | 84 | --- 85 | 86 | 4. `Object` 对象数据类型的基类 87 | `Object.prototype.toString.call()` 最准确最常用的方式 88 | 首先获取Object原型上的toString方法, 让方法执行,并且改变方法中的this关键字的指向 89 | 90 | Object.prototype.toString它的作用是返回当前方法的执行主体(方法中this) 所属类的详细信息 91 | 92 | **toString的理解:** 93 | 字面意思应该是转换为字符串, 但是某些toString方法不仅仅是转换为字符串 94 | ```javascript 95 | // Number.prototype.toString把数字转换为字符串 96 | console.log((1).toString()); // Number.prototype.toString -> 转换为字符串 97 | 98 | console.log((128).toString(2/8/10)); // 把数字转换为二进制/八进制/十进制 99 | 100 | console.log((1).__proto__.__proto__.toString()); // Object.prototype.toString -> "[object Object]" 101 | ``` 102 | > 对于Number/String/Boolean/Array/RegExp/Date/Function原型上的toString方法都是把当前的数据类型转换为字符串的类型(作用仅仅是用来转换为字符串的) 103 | 104 | ![toString](http://img.uplyw.com/note/20180621231444.jpg) 105 | 106 | > Object.prototype.toString并不是用来转换为字符串的 107 | 108 | ![toString](http://img.uplyw.com/note/20180621232223.jpg) 109 | 110 | ```javascript 111 | var ary = []; 112 | console.log(Object.prototype.toString.call(ary)); // -> "[object Array]" 113 | console.log(Object.prototype.toString.call(ary)); // -> [object Array]" 114 | console.log(({}).toString.call(new Date)); // -> "[object Date]" 115 | 116 | console.log(Object.prototype.toString.call(12)); // -> "[object Number]" 117 | console.log(Object.prototype.toString.call("lilei")); // -> "[object String]" 118 | console.log(Object.prototype.toString.call(true)); // -> "[object Boolean]" 119 | console.log(Object.prototype.toString.call(undefined));// -> "[object Undefined]" 120 | console.log(Object.prototype.toString.call(null)); // -> "[object Null]" 121 | console.log(Object.prototype.toString.call(function(){})); // -> "[object Function]" 122 | ``` 123 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十三之字符串及常用方法.md: -------------------------------------------------------------------------------- 1 | ### 字符串常用方法 2 | > 在js中用单(双)引号包起来的都是字符串 3 | 4 | ```javascript 5 | var str = "welcome to javascript,good good study,day day up!" 6 | // -> 字符创就是由零到多个字符组成的 7 | ``` 8 | - 索引 9 | 10 | > 字符串中的第一个字符索引是0 11 | > 字符串中的第二个字符索引是1 12 | > ... 13 | > 以数字作为索引,从零开始 14 | > 字符串中最后一个字符的索引为`length-1` 15 | > 如果指定的索引不存在,输出的结果为`undefined` 16 | 17 | ```javascript 18 | str[0] // -> 'w' 19 | str[str.length-1] // -> '!' 20 | str[100] // -> undefined 21 | ``` 22 | - 长度 23 | 24 | > 有一个叫做length的属性,存储的是当前字符串中字符的个数(字符串的长度) 25 | 26 | ```javascript 27 | str.length // -> 49 28 | ``` 29 | 30 | > 真实项目中,我们经常操作字符串,此时我们需要掌握常用的一些字符串操作方法 31 | > `console.dir(String.prototype)` -> 查看字符串的所有方法 32 | 33 | - charAt() 34 | 35 | > str.charAt(索引): 返回指定所索引位置的字符串 36 | > 和str[索引]的区别在于,当指定的索引不存在的时候,中括号的方式获取的是undefined,而charAt获取的是空字符串 37 | 38 | ```javascript 39 | str.charAt(0) // -> 'w' 40 | str.charAt(str.length - 1) // -> '!' 41 | str.charAt(100) // -> '' 42 | ``` 43 | 44 | - charCodeAt() 45 | 46 | > str.charCodeAt(索引): 在charAt基础上,把获取的字符变为Unicode编码值(对应ASCII码表) 47 | > 48 ~ 57: 0 - 9 48 | > 65 ~ 90: A - Z 49 | > 97 ~ 122: a - z 50 | > ... 51 | 52 | ```javascript 53 | str.charCodeAt(0) // -> 119 54 | String.fromCharCode(119) // -> 'w' 以ASCII码表数值找到对应的字符 55 | ``` 56 | - sunstr() & substring() & slice() 57 | 58 | > str.substr(n,m): 截取字符串,从索引n开始,截取m个字符; 59 | > str.substring(n,m): 截取字符串,从索引n开始,截取到索引m处(不包含m,把找到部分截取) 60 | > str.slice(n,m): 和substring语法一样,区别在于slice支持以负数做索引 61 | > 当索引是负数的时候,浏览器在处理的时候,是用字符串的总长度加上负数索引,然后按照正数处理操作 62 | > + 细节 63 | > 1. 如果只写n(str.substr(n)&str.substring(n)&str.slice(n)),是从n处截取到字符串末尾; 64 | > 2. 如果传递的索引`m`超出最大限制,也是把能截取的部分截取到 65 | > 3. 如果一个参数都不传递的话,相当于把整个字符串截取(字符串的克隆) 66 | 67 | 68 | 69 | ```javascript 70 | str.substr(3,7) // -> "come to" 71 | str.substring(3,7) // -> "come" 72 | str.slice(3,7) // -> 'come' 73 | 74 | str.substring(-7,-3) // -> '' 75 | str.slice(-7,-3) // -> 'day ' => str.slice(str.length-7,string-3) 76 | 77 | ``` 78 | - toUpperCase & toLowerCase 79 | 80 | ```javascript 81 | // 全部转换为大写 82 | str.toUpperCase() 83 | // "WELCOME TO JAVASCRIPT,GOOD GOOD STUDY,DAY DAY UP!" 84 | 85 | // 全部转换为小写 86 | str.toLowerCase() 87 | // "welcome to javascript,good good study,day day up!" 88 | ``` 89 | 90 | - indexOf & lastIndexOf 91 | 92 | > str.indexOf(): 获取当前字符在字符串中第一次出现的位置 93 | > str.lastIndexOf(): 获取当前字符在字符串中最后一次出现的位置 94 | 95 | ```javascript 96 | str.indexOf(',') // -> 21 97 | str.lastIndexOf(',') // -> 37 98 | 99 | // 字符串中不存在的字符 结果为 -1 100 | str.indexOf('#') // -> -1 101 | ``` 102 | > 如果当前字符在字符串中没有出现过,结果是-1; 我们根据这个规律可以验证一下当前字符串中是否包含某个字符 103 | 104 | ```javascript 105 | if(str.indexOf('?') === -1){ 106 | // -> 字符串中不存在该字符 107 | } 108 | 109 | if(str.indexOf('?') >= 0){ 110 | // -> 字符串中存在该字符 111 | } 112 | ``` 113 | - split 114 | 115 | > str.split(): 按照某一个字符把字符串拆分成数组中的某一项,和数组中的join对应 116 | 117 | ```javascript 118 | var hobbyList = "music|movie|sport|read" 119 | hobbyList.split('|') // -> ["music", "movie", "sport", "read"] 120 | 121 | // 如果不存在要分割的字符,则把字符串作为一个元素存在数组中 122 | hobbyList.split('#') // -> ["music|movie|sport|read"] 123 | 124 | 125 | // 如果要分割的字符在字符串中最后一位,则分割出的数组会在最后添加一个空字符串作为数组的一个元素 126 | var hobbyList = "music|movie|sport|read|" 127 | hobbyList.split('|') // -> ["music", "movie", "sport", "read", ""] 128 | 129 | // split支持正则的规则拆分 130 | var str = "name=lilei&age=18"; 131 | str.split(/=|&/g) // -> ["name", "lilei", "age", "18"] 132 | ``` 133 | - replace 134 | 135 | > str.replace(): 实现字符串的替换 136 | > 执行一次replace只能替换一次,如果有好几个都需要替换,在不使用正则的情况下我们需要执行很多次replace 137 | 138 | ```javascript 139 | var str = 'his name is lilei,his name is lilei'; 140 | str.replace('lilei','李雷') // -> "his name is 李雷,his name is lilei" 141 | 142 | // 有些需求即使执行多次replace也实现不了,此时需要使用正则处理,真实项目中replace一般是和正则搭配使用的 143 | var str = 'his name is lilei,his name is lilei'; 144 | str.replace(/lilei/g,"李雷") // -> "his name is 李雷,his name is 李雷" 145 | ``` 146 | - trim & trimLeft(trimStart) & trimRight(trimEnd) 147 | 148 | > str.trimLeft(): 去除字符串开始的空格 149 | > str.trimRight(): 去除字符串开始的空格 150 | > str.trim(): 去除首尾空格 151 | 152 | ```javascript 153 | var str = " javascript " 154 | str.trimLeft() // -> "javascript " 155 | str.trimRight() // -> " javascript" 156 | str.trim() // -> “javascript 157 | ``` 158 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十之for循环练习.md: -------------------------------------------------------------------------------- 1 | 2 | ### 练习 3 | 4 | **隔行变色(css3实现)** 5 | 6 | *HTML* 7 | 8 | ```html 9 |
    10 |
  • 1
  • 11 |
  • 2
  • 12 |
  • 3
  • 13 |
  • 4
  • 14 |
  • 5
  • 15 |
  • 6
  • 16 |
  • 7
  • 17 |
  • 8
  • 18 |
  • 9
  • 19 |
  • 10
  • 20 |
21 | ``` 22 | *CSS* 23 | ```css 24 | *{ 25 | padding: 0; 26 | margin: 0; 27 | } 28 | .numList{ 29 | width: 500px; 30 | margin: 100px auto; 31 | border: 1px solid #ddd; 32 | } 33 | .numList li{ 34 | height: 36px; 35 | line-height: 36px; 36 | text-align: center; 37 | font-size: 20px; 38 | list-style: none; 39 | } 40 | /*单数行*/ 41 | .numList li:nth-child(odd){ 42 | background: #00a1d6; 43 | } 44 | /*双数行*/ 45 | .numList li:nth-child(even){ 46 | background: #ffafc9 47 | } 48 | ``` 49 | **隔行变色(js实现)** 50 | 51 | *HTML同上* 52 | 53 | *JS* 54 | 55 | ```javascript 56 | // 三行变色 57 | var numList = document.getElementsByTagName('li'); 58 | for(var i =0;i < numList.length;i++){ 59 | if(i%3 === 0){ 60 | numList[i].style.background = '#ff0000'; 61 | }else if (i%3 === 1) { 62 | numList[i].style.background = '#00ff00'; 63 | }else{ 64 | numList[i].style.background = '#0000ff'; 65 | } 66 | } 67 | ``` 68 | 69 | --- 70 | 71 | **选项卡** 72 | 73 | *HTML* 74 | 75 | ```html 76 |
77 |
    78 |
  • 新闻
  • 79 |
  • 电影
  • 80 |
  • 综艺
  • 81 |
82 |
朝韩领导人会见
83 |
复仇者联盟3
84 |
奔跑吧兄弟
85 |
86 | ``` 87 | *CSS* 88 | ```css 89 | *{padding: 0;margin: 0;font-family: sans-serif;} 90 | #tabBox{width: 800px;margin: 50px auto;position: relative;} 91 | ul{position: absolute;z-index: 999} 92 | ul:after{display: block;content: "";visibility: hidden;height: 0;clear: both;} 93 | li{width: 100px;height: 36px;line-height: 36px;background: #eee;text-align: center;float: left;list-style: none;margin-right: 12px;border: 1px solid #999; border-bottom: none;cursor: pointer;} 94 | li.active{background: #fff;height: 37px} 95 | #tabBox div{width: 798px;height: 400px;border: 1px solid #999;display: none;position: absolute;top: 37px;} 96 | #tabBox div.active{display: block;line-height: 400px;text-align: center;font-size: 24px;} 97 | ``` 98 | *JS(方法一)* 99 | ```javascript 100 | var tabbox = document.getElementById('tabBox'); 101 | var oLi = tabbox.getElementsByTagName('li'); 102 | var oDiv = tabbox.getElementsByTagName('div'); 103 | function change(index) { 104 | for (var i = 0; i < oLi.length; i++) { 105 | oLi[i].className = ""; 106 | oDiv[i].className = ""; 107 | } 108 | oLi[index].className = 'active'; 109 | oDiv[index].className = 'active'; 110 | } 111 | for (var i = 0; i < oLi.length; i++) { 112 | oLi[i].myIndex = i; 113 | oLi[i].onclick = function(){ 114 | change(this.myIndex) 115 | } 116 | } 117 | ``` 118 | --- 119 | *JS(方法二)* 120 | 121 | ```javascript 122 | for (var i = 0; i < oLi.length; i++) { 123 | ~function(i){ 124 | oLi[i].onclick = function(){ 125 | change(i) 126 | } 127 | }(i) 128 | } 129 | ``` 130 | --- 131 | *JS(方法三)* 132 | 133 | ```javascript 134 | for (let i = 0; i < oLi.length; i++) { 135 | oLi[i].onclick = function(){ 136 | change(i) 137 | } 138 | } 139 | ``` 140 | --- 141 | *JS(方法四)* 142 | 143 | ```javascript 144 | for (var i = 0; i < oLi.length; i++) { 145 | oLi[i].myIndex = i; 146 | oLi[i].onclick = function(index){ 147 | for (var j = 0; j < oLi.length; j++) { 148 | oLi[j].className = oDiv[j].className = ""; 149 | } 150 | this.className = oDiv[this.myIndex].className = "active" 151 | } 152 | } 153 | ``` 154 | --- 155 | *JS(方法五)* 156 | 157 | ```javascript 158 | var tabbox = document.getElementById('tabBox'); 159 | var oLi = tabbox.getElementsByTagName('li'); 160 | var oDiv = tabbox.getElementsByTagName('div'); 161 | 162 | // 记录上一个选中li的索引 163 | var previousIndex = 0; 164 | 165 | for (var i = 0; i < oLi.length; i++) { 166 | // 分别给每一个li设置一个自定义属性记录当前li索引 167 | oLi[i].currentIndex = i; 168 | 169 | oLi[i].onclick = function(){ 170 | // 如果点击的li和当前li相同则不执行 171 | if(this.currentIndex === previousIndex){ 172 | return; 173 | } 174 | // 清空上一个li的样式 175 | oLi[previousIndex].className = oDiv[previousIndex].className = null; 176 | // 给点击的里设置样式 177 | this.className = oDiv[this.currentIndex].className = "active"; 178 | // 把上一个li的索引更新到当前li 179 | previousIndex = this.currentIndex; 180 | } 181 | } 182 | ``` 183 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十二之数组排序算法-冒泡,递归,快速,插入.md: -------------------------------------------------------------------------------- 1 | #### 冒泡排序 2 | 3 | > 原理: 让数组中的当前项和后一项进行比较, 如果当前项大于后一项,我们让两者交换位置(小 -> 大) 4 | 5 | ```javascript 6 | var ary = [12,13,23,14,16,11] 7 | 8 | // 第一轮比较: 9 | // 12 13 [12,13,23,14,16,11] 10 | // 13 23 [12,13,23,14,16,11] 11 | // 23 14 [12,13,14,23,16,11] 12 | // 23 16 [12,13,14,16,23,11] 13 | // 23 11 [12,13,14,16,11,23] 14 | // 第二轮比较: 15 | // 12 13 [12,13,14,16,11,23] 16 | // 13 14 [12,13,14,16,11,23] 17 | // 14 16 [12,13,14,16,11,23] 18 | // 16 11 [12,13,14,11,16,23] 19 | // ... 20 | 21 | // 每一轮从前到后两两比较,虽然不一定实现最后的排序效果,但是可以把当前最大的放到末尾 22 | // 具体比较轮数: ary.length-1; 数组有多长,我们只需把总长度-1个数分别放在末尾,即可实现最后的排序 23 | 24 | // 第一轮比较5次: 一共6个,不需要和自己比较 25 | // 第二轮比较4次: 一共6个,不用和自己比较,也不用和第一轮放在末尾的那个最大值比较 26 | // 第三轮比较3次: 27 | // ... 28 | 29 | // 每一轮比较的次数: 30 | //ary.length-1(不用和自己比较) - 当前已经执行的轮数(执行一轮向末尾放一个最大值,这些值不需要再比较) 31 | 32 | // a = 12; 33 | // b = 13; 34 | // a和b交换值 35 | 36 | // 借用第三个变量先存储一个值,然后替换 37 | // c = a; 38 | // a = b; 39 | // b = c; 40 | 41 | // 不借用三个变量 42 | // a = a+b; // -> 25 43 | // b = a-b; // -> 12 -> b = 12; 44 | // a = a-b; // -> 13 -> a = 13; 45 | 46 | // bubble: 冒泡排序 47 | // @parameter 48 | // ary: [array]需要实现排序的数组 49 | // @return 50 | // [array]排序后的数组(升序) 51 | // by team on 2018/05/16 52 | 53 | // 升序 54 | function bubble(ary){ 55 | // 外层循环控制的是比较的轮数 56 | for (var i = 0; i < ary.length-1; i++) { 57 | // 内层循环控制每一轮比较的次数 58 | for (var j = 0; j < ary.length-1-i; j++) { 59 | // ary[j]: 当前本次拿出来的这一项 60 | // ary[j+1]: 当前项的后一项 61 | if (ary[j] > ary[j+1]) { 62 | // 当前项这一项比后一项还要大,我们让两项交换位置 63 | var temp = ary[j]; 64 | ary[j] = ary[j+1]; 65 | ary[j + 1] = temp; 66 | } 67 | } 68 | } 69 | return ary; 70 | } 71 | console.log(bubble(ary)) 72 | 73 | // 降序 74 | function bubble(ary){ 75 | for (var i = 0; i < ary.length-1; i++) { 76 | for (var j = 0; j < ary.length-1-i; j++) { 77 | if (ary[j] < ary[j+1]) { 78 | var temp = ary[j]; 79 | ary[j] = ary[j+1]; 80 | ary[j + 1] = temp; 81 | } 82 | } 83 | } 84 | return ary; 85 | } 86 | console.log(bubble(ary)) 87 | ``` 88 | 89 | #### 递归排序 90 | 91 | > 自己调用自己 92 | 93 | ```javascript 94 | // 死递归 95 | function fn(num){ 96 | console.log(num) 97 | fn() 98 | } 99 | fn(10) 100 | 101 | 102 | function fn(num){ 103 | console.log(num) 104 | if(mun === 1){ 105 | return 106 | } 107 | fn(num - 1) 108 | } 109 | fn(10) 110 | ``` 111 | - 面试题: 1-100之间, 把所有能被3整除并且能被5整除的获取到,然后累加求和 112 | 113 | ```javascript 114 | // 方案一: 115 | var total = null; 116 | for(var i=1;i< 100;i++){ 117 | if(i%3 === 0 && i%5 === 0){ 118 | console.log(i) 119 | total += i; 120 | } 121 | } 122 | console.log(total) 123 | ``` 124 | ```javascript 125 | // 方案二 126 | function fn(num){ 127 | if(num>100){ 128 | return 0; 129 | } 130 | if(num%15 === 0){ 131 | return num + fn(num + 1); 132 | } 133 | return fn(num+1) 134 | } 135 | console.log(fn(1)) 136 | ``` 137 | ```javascript 138 | function fn(num){ 139 | if(num<1){ 140 | return 1; 141 | } 142 | if(num%2 === 0){ 143 | return num * fn(num -1); 144 | } 145 | return fn(num -1) 146 | } 147 | var result = fn(10); 148 | console.log(result) 149 | ``` 150 | 151 | #### 快速排序 152 | 153 | > 先找中间这一项 154 | > 把剩余项的每一个值和中间项进行比较,比他小的放在左边,比他大的放在右边(新数组) 155 | > ... 156 | 157 | ```javascript 158 | var ary = [12,15,14,13,16,11]; 159 | function quick(ary){ 160 | // 如果传递进来的数组只有一项或者是空的,我们则不再继续取中间项拆分 161 | if(ary.length <= 1){ 162 | return ary; 163 | } 164 | // 获取中间项的索引: 把中间项的值获取到,在原有数组中删除中间项 165 | var centerIndex = Math.floor(ary.length/2), 166 | // splice返回的是个数组,数组中包含了删除的那个内容 167 | centerValue = ary.splice(centerIndex,1)[0]; 168 | 169 | // 用剩余数组中的每一项和中间项比较,比中间项大的放在右边,比中奖项小的放在左边(左右两边都是新数组) 170 | var aryLeft = [], 171 | aryRight = []; 172 | for (var i = 0; i < ary.length; i++) { 173 | var cur = ary[i]; 174 | cur < centerValue?aryLeft.push(cur):aryRight.push(cur); 175 | } 176 | return quick(aryLeft).concat(centerValue, quick(aryRight)); 177 | } 178 | console.log(quick(ary)) 179 | ``` 180 | 181 | #### 插入排序 182 | 183 | ```javascript 184 | var ary = [12,15,14,13,16,11]; 185 | function insert(ary){ 186 | // 先抓一张牌(一般都抓第一张) 187 | var handAry = []; // 存储的是手里已经抓取的牌 188 | handAry.push(ary[0]); 189 | 190 | // 一次循环抓取后面的牌 191 | for (var i = 1; i < ary.length; i++) { 192 | var item = ary[i]; // 本次新抓的这张牌 193 | 194 | // 拿新抓的牌和手里现有的牌比较 195 | for (var j = handAry.length-1; j >= 0; j--) { 196 | // handAry[j]: 当前比较的手里的这张牌 197 | // 新抓的牌比当前比较的这张牌大了,我们把新抓的牌放在他的后面 198 | if(item>handAry[j]){ 199 | handAry.splice(j+1,0,item); 200 | break; 201 | } 202 | if(j === 0){ 203 | // 新传的牌是最小的,把新抓的牌放在最开始的位置 204 | handAry.unshift(item); 205 | } 206 | } 207 | } 208 | return handAry; 209 | } 210 | console.log(insert(ary)) 211 | ``` 212 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十七之DOM操作-增删改.md: -------------------------------------------------------------------------------- 1 | ### DOM的赠删改 2 | 3 | #### 增 4 | 5 | > 真是项目中, 我们会在js中动态创建一些html标签, 然后把其增加到页面中 6 | 7 | - document.createElement 8 | 9 | > 在js中动态创建一个html标签 10 | 11 | - appendChild 12 | 13 | > 容器.appendChild(新元素) 14 | > 把当前创建的新元素添加到容器的末尾位置 15 | 16 | - insertBefore 17 | 18 | > 容器.insertBefore(新元素,老元素) 19 | > 把当前容器中, 把新元素增加到老元素之前 20 | 21 | ```html 22 | 23 |
2
24 | 27 | 39 | 40 | ``` 41 | ```javascript 42 | // -> 真实项目中很多需求都是通过动态常见元素来完成的,其中有一个需求; 解析一个URL地址每一部分的信息(包含问号传递的参数值) 43 | // -> 1. 纯字符串拆分截取; 44 | // -> 2. 编写强大的正则,捕获到需要的结果; 45 | // -> 3. 通过动态创建一个a标签, 利用a标签的一些内置属性来分别获取每一部分的内容; 46 | // -> ... 47 | 48 | var link = document.createElement('a'); 49 | link.href = 'http://www.example.com/school/?name=lilei&age=18&sex=0#student'; // -> 此处地址就是我们需要解析的url 50 | console.dir(link); 51 | // -> hash: 存储了哈希值 '#student' 52 | // -> hostname: 域名 'www.example.com' 53 | // -> pathname: 路径 '/school/' 54 | // -> protocol: 协议 'http:' 55 | // -> search: 问号传递参数值没有传递是空字符串 '?name=lilei&age=18&sex=0' 56 | ``` 57 | ```javascript 58 | function queryURLParameter(url){ 59 | var link = document.createElement('a'); 60 | link.href = url; 61 | var search = link.search, 62 | obj = {}; 63 | if(search.length === 0) return; 64 | search = search.substr(1).split(/&|=/g); 65 | for(var i=0;i {name: "lilei", age: "18", sex: "0"} 76 | ``` 77 | 78 | #### 删 改 79 | 80 | - removeChild 81 | 82 | > 容器.removeChild(元素) 83 | > 在当前容器中把某一个元素移除掉 84 | 85 | - replaceChild 86 | 87 | > 容器.replaceChild(新元素,老元素) 88 | > 在当前容器中, 拿新元素替换老元素 89 | 90 | - cloneNode 91 | 92 | > 元素.cloneNode(false/true) 93 | > 把原有的元素克隆一份一模一样的 94 | > false: 只克隆当前元素本身 95 | > true: 深度克隆, 把当前元素本身以及元素的所有后代都进行克隆 96 | 97 | ```html 98 | 106 |
1
107 |
12
108 | 115 | ``` 116 | 117 | - [set/get/remove]Attribute 118 | 119 | > 给当前元素设置/获取/移除 属性的(一般操作的都是他的自定义属性) 120 | > box.setAttribute('myIndex',0) 121 | > box.getAttribute('myIndex') 122 | > box.removeAttribute('myIndex') 123 | > 124 | > 使用 `xxx.index=0` 和 `xxx.setAttribute('index',0)` 这两种设置自定义属性的区别? 125 | > xxx.index: 是把当前操作的元素当做一个普通对象,为其设置一个属性名(和页面中的html标签没什么关系) 126 | > xxx.setAttribute: 把元素当做特殊的元素对象来处理,设置的自定义属性是和页面结构中的DOM元素映射在一起的 127 | 128 | ```html 129 |
130 | 137 | ``` 138 | 139 | > - js中获取的元素对象,我们可以把它理解为两种角色 140 | > 1. 与页面html结构无关的普通对象 141 | > 2. 与页面html结构存在映射关系的元素对象 142 | > 143 | > - 元素对象中的内置属性,大部分都和页面的标签存在映射关系: 144 | > xxx.style.backgroundColor = 'xxx';此时不仅把js对象对应的属性值改变了,而且也会映射到页面的html标签上(标签中有一个style行内样式, 元素的样式改变了) 145 | > xxx.className = 'xxx': 此时不仅是把js对象中的属性值改变了,而且页面中的标签增加了class样式类(可以看见的) 146 | > 147 | > - 元素对象中的自定义属性: 148 | > xxx.index=0: 仅仅是把js对象中增加了一个属性名(自定义的),和页面中的html没啥关系(在结构上看不见) 149 | > xxx.setAttribute: 通过这种方式设置的自定义属性和之前提到的内置属性差不多,都是和html结构存在映射关系的(设置的自定义属性可以呈现在结构上) 150 | 151 | ```javascript 152 | // -> 获取当前元素的上一个哥哥元素节点(兼容所有浏览器) 153 | // -> curEle: current element 154 | 155 | // 思路: 156 | // 首先获取当前元素的上一个哥哥节点,判断当前获取的节点是否为元素节点(nodeType === 1),如果不是,基于当前获取的节点,找他的上一个哥哥节点...一直到找到的节点为元素节点为止 157 | // 如果在查找过程中,发现没有上一个哥哥节点了,则不在继续查找 158 | 159 | // while(条件){循环体} 160 | 161 | function prev(curEle){ 162 | // 获取当前元素的上一个节点 163 | var p = curEle.previousSibling; 164 | // 如果存在上一个节点并且该节点不是元素节点 165 | while(p && p.nodeType !== 1){ 166 | // 就再往上一个节点继续查找 167 | p = p.previousSibling; 168 | } 169 | // 直到找到返回 170 | return p; 171 | } 172 | 173 | // 扩展: 174 | // next: 获取下一个弟弟元素节点 175 | // prevAll: 获取所有的哥哥元素节点 176 | // nextAll: 获取所有的弟弟元素节点 177 | // siblings: 获取所有的兄弟元素节点 178 | // index: 获取当前元素在兄弟元素节点中的索引 179 | // ... 180 | ``` 181 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记四十三之json操作及DOM回流.md: -------------------------------------------------------------------------------- 1 | #### json介绍 2 | 3 | - 后台 -> 提供一个数据请求的接口,前端通过接口地址可以请求到后台的数据 4 | - 前端 -> 前端得到数据后,需要进行数据解析, 把数据绑定在html页面上 -> "数据绑定" 5 | 6 | ``` 7 | sequenceDiagram 8 | 前端->>后台: 发送请求获取数据 9 | 后台->>前端: 把准备好的数据返回给前端 10 | 后台-->>前端: (后台给前端返回的数据一般都是json格式的) 11 | ``` 12 | 13 | - json不是一个单独的数据类型,它只是一种特殊的数据格式 -> 它是对象数据类型的 14 | 15 | ```javascript 16 | var obj = {name:"lilei", age: 18}; // 普通格式对象 17 | var jsonObl = {"name":"lilei","age":17}; // json格式对象 18 | // 相对于普通的格式来说,只是把属性名用双引号包起来了(只能是双引号) 19 | ``` 20 | - 在window浏览器对象中,提供了一个叫json的属性, 它这里面提供了两个方法: 21 | 1. JSON.parse -> 把JSON格式的字符串转换为JSON格式的对象 22 | 2. JSON.stringify -> 把JSON格式的对象转换为JSON格式的字符串 23 | 24 | ```javascript 25 | var jsonObj = {"name":"lilei","age":17}; 26 | var jsonStr = JSON.stringify(jsonObj); 27 | console.log(jsonStr) // '{"name":"lilei","age":17}' 28 | console.log(JSON.parse(jsonStr))// {name: "lilei", age: 17} 29 | ``` 30 | 31 | > 在ie6~7浏览器中,我们的window下没有JSON对象,刚才的parse和stringify都不存在了 32 | 33 | ```javascript 34 | // 把JSON格式的对象转换为JSON格式的字符串 35 | var str = '{"name":"lilei","age":17}'; 36 | JSON.parse(str); 37 | eval("(" + str + ")"); // 使用eval,不要忘记手动的加一个小括号 38 | ``` 39 | 40 | #### json数据绑定 41 | 42 | - json.html 43 | 44 | ```html 45 | 77 |
    78 |
  • 01aaaaaaaaaaaaa
  • 79 |
  • 02bbbbbbbbbbbbb
  • 80 |
  • 03ccccccccccccc
  • 81 |
82 | 83 | ``` 84 | 85 | - json.js 86 | 87 | ```javascript 88 | var jsonObj = [ 89 | { 90 | "title":"qqqqqqqqqqqqqq", 91 | "desc":"q1q1q1q1q1q1q1q1q1q1q1" 92 | }, 93 | { 94 | "title":"wwwwwwwwwwwwww", 95 | "desc":"w2w2w2w2w2w2w2w2w2w2w2" 96 | }, 97 | { 98 | "title":"eeeeeeeeeeeeee", 99 | "desc":"e1e1e1e1e1e1e1e1e1e1e1" 100 | }, 101 | { 102 | "title":"rrrrrrrrrrrrrr", 103 | "desc":"r1r1r1r1r1r1r1r1r1r1r1" 104 | }, 105 | { 106 | "title":"tttttttttttttt", 107 | "desc":"t1t1t1t1t1t1t1t1t1t1t1" 108 | }, 109 | { 110 | "title":"yyyyyyyyyyyyyy", 111 | "desc":"y1y1y1y1y1y1y1y1y1y1y1" 112 | }, 113 | { 114 | "title":"uuuuuuuuuuuuuu", 115 | "desc":"u1u1u1u1u1u1u1u1u1u1u1" 116 | }, 117 | { 118 | "title":"iiiiiiiiiiiiii", 119 | "desc":"i1i1i1i1i1i1i1i1i1i1i1" 120 | } 121 | ] 122 | ``` 123 | 124 | ```javascript 125 | var oUl = document.getElementById("ul1"); 126 | var oLis = oUl.getElementsByTagName("li"); 127 | 128 | // 鼠标移入移出,背景变色 129 | for (var i = 0; i < oLis.length; i++) { 130 | oLis[i].onmouseover = function (){ 131 | this.style.backgroundColor = 'pink'; 132 | } 133 | oLis[i].onmouseout = function (){ 134 | this.style.backgroundColor = ''; 135 | } 136 | } 137 | ``` 138 | 1. 利用动态创建元素节点和把它追加到页面中的方式来实现数据绑定 139 | 优势: 把需要动态绑定的内容一个个追加到页面中,对原来的元素没有任何影响 140 | 弊端: 浏览器每创建一个li, 就添加到页面中,引发一次DOM回流,最后引发会留的次数过多, 影响我们的性能 141 | 142 | ```javascript 143 | for (var i = 0; i < jsonObj.length; i++) { 144 | var cur = jsonObj[i]; 145 | var oLi = document.createElement("li"); 146 | var num = i+4 147 | if(num<10){ 148 | num = "0" + num 149 | } 150 | oLi.innerHTML = "" + num + "" + cur.title; 151 | oUl.appendChild(oLi) 152 | } 153 | ``` 154 | 155 | 2. 字符串拼接的方式: 首先循环需要绑定的数据, 然后把需要动态绑定的标签以字符串的方式拼接到一起,拼接完成后, 最后统一添加到页面中 ("字符串拼接绑定数据是工作中最常用的一种绑定数据的方式" -> 模板引擎数据绑定 ) 156 | 优势: 事先把内容拼接好, 最后添加到页面中, 只引发一次回流 157 | 弊端: 把新拼接的字符串添加到 #ul1 中,原有的三个li的鼠标滑过效果都消失了(原来标签绑定的时间都消失了) 158 | 159 | ```javascript 160 | var str = ""; 161 | for (var i = 0; i < jsonObj.length; i++) { 162 | var cur = jsonObj[i]; 163 | var num = i+4 164 | if(num<10){ 165 | num = "0" + num 166 | } 167 | str += "
  • "; 168 | str += "" + num + ""; 169 | str += cur.title; 170 | str += "
  • " 171 | } 172 | // console.log(str); 173 | oUl.innerHTML += str; // -> oUl.innerHTML = oUl.innerHTML + str; 174 | // (把之前的三个 li 以字符串的方式获取到)+str ; 175 | // (拼接完成的整体还是字符串, 最后再把字符串统一的添加到页面中, 浏览器还需要把字符串渲染成对应的标签) 176 | ``` 177 | 178 | 3. 文档碎片 179 | 180 | ```javascript 181 | var frg = document.createDocumentFragment(); 182 | // 创建一个文档碎片, 相当于临时创建一个容器 183 | 184 | for (var i = 0; i < jsonObj.length; i++) { 185 | var cur = jsonObj[i]; 186 | var oLi = document.createElement("li"); 187 | var num = i+4 188 | if(num<10){ 189 | num = "0" + num 190 | } 191 | oLi.innerHTML = "" + num + "" + cur.title; 192 | frg.appendChild(oLi) 193 | } 194 | oUl.appendChild(frg) 195 | frg = null; 196 | ``` 197 | 198 | 199 | #### js中DOM深入知识: 200 | 201 | -> 回流(重排 reflow): 当页面中的结构发生改变(增加/删除元素, 位置发生改变...), 浏览器都需要重新的计算一遍最新的DOM结构, 重新的进行渲染 202 | -> 重绘:某一个元素的部分样式发生改变了, 浏览器只需要重新的渲染当前元素即可 203 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记三十六之原型链模式扩展(3).md: -------------------------------------------------------------------------------- 1 | 2 | > for in 循环在遍历的时候, 默认的话可以吧自己的私有的和在它所属类原型上扩展的属性和方法都可以遍历到, 但是一般情况下, 我们遍历一个对象只需要遍历私有的即可, 我们可以使用一下的判断进行处理 3 | 4 | ```javascript 5 | Object.prototype.aaa = function(){}; 6 | 7 | var obj = {name:"lilei",age:18} 8 | for(var key in obj){ 9 | // if(obj.propertyIsEnumerable(key)){ 10 | // console.log(key) 11 | // } 12 | 13 | if(obj.hasOwnProperty(key)){ 14 | console.log(key) 15 | } 16 | } 17 | ``` 18 | 19 | > Object.create()方法创建一个拥有指定原型和若干个指定属性的对象 20 | 21 | ```javascript 22 | Object.create() 23 | 24 | var obj = { 25 | constructor: Fn, 26 | getX: function(){ 27 | 28 | } 29 | }; 30 | function Fn(){ 31 | 32 | } 33 | Fn.prototype = obj; 34 | Fn.prototype.sum = function(){ 35 | 36 | } 37 | ``` 38 | > Object.create()创建一个新的对象, 但是还要把proObj作为这个对象的原型(ie6~8不支持[ECMAscript5]) 39 | 40 | ```javascript 41 | var obj = { 42 | getX : function (){ 43 | 44 | } 45 | }; 46 | var obj2 = Object.create(obj) 47 | // obj2: 48 | // __proto__: 49 | // getX:function... 50 | // __proto__:Object.prototype 51 | obj2.getX(); 52 | obj.getY = function (){ 53 | console.log("ok"); 54 | } 55 | obj2.getY() // -> ok 56 | ``` 57 | 58 | ```javascript 59 | function object(obj){ 60 | function Fn(){ 61 | 62 | } 63 | Fn.prototype = obj; 64 | return new Fn; 65 | } 66 | ``` 67 | 68 | #### 原型继承 69 | 70 | ```javascript 71 | // #div1.__proto__ -> HTMLDivElement.prototype -> HTMLElement.prototype -> Element.prototype -> Node.prototype -> EventTarget.prototype -> Object.prototype 72 | 73 | function myObject(){ 74 | 75 | } 76 | myObject.prototype = { 77 | constructor: myObject, 78 | hasOwnproperty: function(){ 79 | 80 | } 81 | }; 82 | function myEventTarget(){ 83 | 84 | } 85 | myEventTarget.prototype = new myObject(); 86 | myEventTarget.prototype.addEventListener=function(){ 87 | 88 | } 89 | function myNode(){ 90 | 91 | }; 92 | myNode.prototype=new myEventTarget; 93 | myNode.prototype.createElement=function(){ 94 | 95 | } 96 | var n =new myNode; 97 | ``` 98 | 99 | ```javascript 100 | function A(){ 101 | this.x=100; 102 | } 103 | A.prototype.getX=function(){ 104 | console.log(this.x); 105 | } 106 | function B(){ 107 | this.y=200; 108 | } 109 | B.prototype=new A; 110 | ``` 111 | > `原型继承`是js中最常用的一种继承方式 112 | > 子类B想要继承父类A中的所有的属性和方法(私有和公有),只需要让B.prototype=new A;即可 113 | > 原型继承的特点: 它是把父类中的私有的+公有的都继承到了子类原型上(子类公有的) 114 | > ->核心: 原型继承并不是把父类中的属性和方法克隆一份一模一样的给B,而是让B和A之间增加了原型链的连接,以后B的实例n想要用A中的的getX方法,需要一级级的向上查找来使用 115 | 116 | #### call继承 117 | 118 | ```javascript 119 | function A(){ 120 | this.x = 100; 121 | } 122 | A.prototype.getX = function(){ 123 | console.log(this.x); 124 | }; 125 | 126 | function B(){ 127 | // this -> n 128 | A.call(this); // -> A.call(n) 把A执行让A中的this变为了n 129 | } 130 | var n = new B; 131 | console.log(n.x) // 100 132 | ``` 133 | 134 | > `call继承`: 把父类私有的属性和方法 克隆一份一模一样的作为子类私有的属性; 135 | 136 | #### 冒充对象继承 137 | 138 | ```javascript 139 | function A(){ 140 | this.x = 100; 141 | } 142 | A.prototype.getX = function(){ 143 | console.log(this.x); 144 | }; 145 | 146 | function B(){ 147 | // this -> n 148 | var temp = new A; // 创建A对象的实例 149 | for(var key in temp){ 150 | // console.log() 151 | this[key] = temp[key]; 152 | } 153 | tamp = null 154 | } 155 | var n = new B; 156 | console.log(n.x) // 100 157 | ``` 158 | 159 | > `冒充对象继承`: 把父类私有的+公有的克隆一份一模一样的给子类私有的 160 | 161 | #### 混合模式继承 162 | 163 | ```javascript 164 | function A(){ 165 | this.x = 100; 166 | } 167 | A.prototype.getX = function(){ 168 | console.log(this.x); 169 | }; 170 | 171 | function B(){ 172 | A.call(this); // -> n.x = 100; 173 | } 174 | 175 | B.prototype = new A; // -> B.prototype: x= 100 getX... 176 | B.prototype.constructor = B; 177 | var n = new B; 178 | console.log(n.x) // 100 179 | ``` 180 | 181 | > `混合模式继承`: 原型继承 + call继承 182 | 183 | #### 寄生组合式继承 184 | 185 | ```javascript 186 | function A(){ 187 | this.x = 100; 188 | } 189 | A.prototype.getX = function(){ 190 | console.log(this.x); 191 | }; 192 | 193 | function B(){ 194 | A.call(this); 195 | } 196 | 197 | // B.prototype = Object.create(A.prototype); 198 | B.prototype = objectCreate(A.prototype); 199 | B.prototype.constructor = B; 200 | var n = new B; 201 | console.dir(n); 202 | 203 | function objectCreate(o){ 204 | function fn(){ 205 | 206 | } 207 | fn.prototype = o; 208 | } 209 | ``` 210 | 211 | #### 中间类继承法(不兼容) 212 | 213 | ```javascript 214 | // 求平均数 215 | 216 | function avgFn(){ 217 | Array.prototype.sort.call(arguments,function(a,b){ 218 | return a-b; 219 | }); 220 | Array.prototype.pop.call(arguments); 221 | Array.prototype.shift.call(arguments); 222 | return (eval(Array.prototype.join.call(arguments,"+")) / arguments.length).toFixed(2); 223 | } 224 | console.log(avgFn(1,2,21,3,43,12,563,2,54)) 225 | ``` 226 | 227 | ```javascript 228 | // 求平均数 229 | 230 | function avgFn(){ 231 | arguments.__proto__ = Array.prototype; 232 | arguments.sort(function(a,b){ 233 | return a-b; 234 | }); 235 | arguments.pop(); 236 | arguments.shift(); 237 | return (eval(arguments.join("+")) / arguments.length).toFixed(2); 238 | } 239 | console.log(avgFn(1,2,21,3,43,12,563,2,54)) 240 | ``` 241 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记十四之Math和字符串方法应用.md: -------------------------------------------------------------------------------- 1 | ### 案例分析 2 | 3 | - **字符串** 4 | 5 | > 获取地址栏中URL地址问号传递的参数值 6 | > https://www.baidu.com/s?wd=javascript&rsv_spt=1&issp=1 7 | > 8 | > 目标: 把问号传递的参数值分别的解析出来 9 | > obj={wd:'javascript',rsv_spt:1,issp:1} 10 | 11 | ```javascript 12 | var str = "https://www.baidu.com/s?wd=javascript&rsv_spt=1&issp=1"; 13 | // -> 目标: {wd:'javascript',rsv_spt:1,issp:1} 14 | 15 | // -> 方案一: 16 | var questionIndex = str.indexOf('?'); 17 | str = str.substring(questionIndex + 1) // -> "wd=javascript&rsv_spt=1&issp=1" 18 | var ary = str.split('&') // -> ["wd=javascript", "rsv_spt=1", "issp=1"] 19 | var obj = {}; 20 | for(var i=0;i {wd: "javascript", rsv_spt: "1", issp: "1"} 29 | ``` 30 | 31 | ```javascript 32 | var str = "https://www.baidu.com/s?wd=javascript&rsv_spt=1&issp=1"; 33 | // -> 目标: {wd:'javascript',rsv_spt:1,issp:1} 34 | 35 | // -> 方案二: 36 | function queryURLParameter(url){ 37 | // -> 传递的参数(我们当前要解析的url地址) 38 | var questionIndex = url.indexOf('?'), 39 | obj = {}; 40 | if(questionIndex === -1){ 41 | // -> url中没有问号传参: 直接返回空对象 42 | return obj; 43 | } 44 | url = url.substring(questionIndex+1), 45 | ary = url.split("&"); 46 | for(var i=0;i {wd: "javascript", rsv_spt: "1", issp: "1"} 54 | 55 | console.log(queryURLParameter("https://www.baidu.com/s?wd=node&rsv_spt=1&issp=1")) 56 | // -> {wd: "node", rsv_spt: "1", issp: "1"} 57 | 58 | console.log(queryURLParameter("https://www.baidu.com/s?wd=前端")) 59 | // -> {wd: "前端"} 60 | ``` 61 | 62 | ```javascript 63 | var str = "https://www.baidu.com/s?wd=javascript&rsv_spt=1&issp=1"; 64 | // -> 目标: {wd:'javascript',rsv_spt:1,issp:1} 65 | 66 | // -> 方案三: 67 | String.prototype.myQueryURLParameter = function myQueryURLParameter(){ 68 | var obj = {}, 69 | reg = /([^?&=]+)=([^?&=]+)/g; 70 | this.replace(reg,function(){ 71 | var arg = arguments; 72 | obj[arg[1]] = arg[2]; 73 | }); 74 | return obj; 75 | } 76 | console.log(str.myQueryURLParameter()) 77 | ``` 78 | - **Math及字符串** 79 | 80 | *随机验证码* 81 | 82 | > 真实项目中的验证码: 83 | > - 真实项目中验证码一般都是后台处理的,后台返回给客户端展示的是一个图片(图片中包含了验证码) 84 | > 85 | > 验证码形式: 86 | > 1. 数字字母 87 | > 2. 问答 88 | > 3. 图片选择 89 | > 4. 文字顺序 90 | > 5. 拖拽 91 | 92 | *HTML/CSS* 93 | ```html 94 | 97 |
    qwer
    98 | ``` 99 | *JavaScript* 100 | ```javascript 101 | // 简单实现 102 | var codeBox = document.getElementById("codeBox"); 103 | var areaStr = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM' 104 | var result = ""; 105 | for(var i=0;i<4;i++){ 106 | // 随机获取一个0-61之间的随机整数: 作为接下来获取字符的索引 107 | var ran = Math.round(Math.random()*61); 108 | // -> 根据索引获取一个随机字符 109 | var str1 = areaStr.charAt(ran) 110 | // -> 把每一次循环获取的字符存放在最后结果中 111 | result += str1 112 | } 113 | codeBox.innerHTML = result 114 | ``` 115 | 116 | ```javascript 117 | // 点击切换 118 | var codeBox = document.getElementById('codeBox'); 119 | function getCode(){ 120 | var result = '', 121 | areaStr = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'; 122 | for (var i = 0; i < 4; i++) { 123 | var ran = Math.round(Math.random()*61); 124 | result += areaStr.charAt(ran); 125 | } 126 | codeBox.innerHTML = result; 127 | } 128 | 129 | // -> 加载页面是需要执行一次这个方法: 生成四位验证码 130 | getCode(); 131 | // -> 点击盒子重新生成验证码(此处不加小括号,这块只是再把函数绑定给点击事件) 132 | codeBox.onclick = getCode; 133 | 134 | ``` 135 | ```javascript 136 | // 四位不重复的验证码 137 | var codeBox = document.getElementById("codeBox"); 138 | function getCode(){ 139 | var result = "", 140 | str = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; 141 | for (var i = 0; i < 4; i++) { 142 | var ran = Math.round(Math.random()*61), 143 | cur = str.charAt(ran); 144 | // -> 验证一下新获取的char字符是否已经在 result 中存在了 145 | // -> 如果存在了我们不存储,重新再获取一遍,反之才累加到 result 中 146 | if (result.indexOf(cur)>-1) { 147 | i--; 148 | continue; 149 | } 150 | result += cur; 151 | } 152 | codeBox.innerHTML = result; 153 | } 154 | getCode() 155 | codeBox.onclick = getCode; 156 | ``` 157 | ```javascript 158 | // 四位大小写不重复的验证码 159 | var codeBox = document.getElementById("codeBox"); 160 | function getCode(){ 161 | var result = "", 162 | str = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; 163 | for (var i = 0; i < 4; i++) { 164 | var ran = Math.round(Math.random()*61), 165 | cur = str.charAt(ran); 166 | // -> 验证一下新获取的char字符是否已经在 result 中存在了 167 | // -> 如果存在了我们不存储,重新再获取一遍,反之才累加到 result 中 168 | if (result.toUpperCase().indexOf(cur.toUpperCase())>-1) { 169 | i--; 170 | continue; 171 | } 172 | result += cur; 173 | } 174 | codeBox.innerHTML = result; 175 | } 176 | getCode() 177 | codeBox.onclick = getCode; 178 | ``` 179 | -------------------------------------------------------------------------------- /javascriptLearnLog/js笔记二十一Array数组检查,遍历,去重.md: -------------------------------------------------------------------------------- 1 | #### 数组检查 2 | - indexOf / lastIndexOf 3 | 4 | > 检验数组中是否包含某一项 5 | > 获取当前项在数组中第一次或者最后一次出现位置的索引 6 | 7 | > 数组中的这两个方法在ie6~7下不兼容 8 | > 字符串中的这两个方法兼容所有浏览器 9 | 10 | > 如果当前数组并没有这一项,返回的索引是 -1 ,我们根据这一点可以验证数组中是否包含这一项 11 | 12 | ```javascript 13 | if(ary.indexOf(12) > -1){ 14 | // -> 数组中包含12 15 | } 16 | 17 | // 自己写的indexOf方法 18 | Array.prototype.myIndexOf = function myIndexOf(value){ 19 | var result = -1; 20 | for(var i=0;i 验证12 是否在数组中 29 | ``` 30 | 31 | #### 数组遍历 32 | 33 | > 以下方法在ie6~8中都不兼容 34 | 35 | - forEach 36 | 37 | > 遍历数组中的每一项 38 | 39 | ```javascript 40 | ary.forEach(function(value,index){ 41 | // -> 数组中有多少项,当前回调函数执行多少次; 42 | // -> 每一次传递进来的value就是当前遍历数组这一项的值,index就是遍历这一项的索引 43 | }) 44 | ``` 45 | 46 | - map 47 | 48 | > 遍历数组中的每一项 49 | > 在forEach的基础上可以修改每一项的值 50 | 51 | ```javascript 52 | ary,map(function(value,index){ 53 | // -> 数组中有多少项,当前回调函数执行多少次; 54 | // -> 每一次传递进来的value就是当前遍历数组这一项的值,index就是遍历这一项的索引; 55 | return xxx; 56 | }) 57 | ``` 58 | - fillter 59 | - find 60 | - reduce 61 | - every 62 | - ... 63 | 64 | #### 数组去重 65 | 66 | - 方案一: 循环去重 67 | 68 | ```javascript 69 | // 思路一 70 | // 遍历数组中的每一项,拿每一项和它后面的项依次比较, 如果相同了, 则把相同的这一项在原来数组中删除即可; 71 | 72 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 73 | for(var i=0;i [1, 2, 2, 3, 3, 5, 4] 90 | // 数组塌陷导致不能完全去重 91 | // 数组塌陷问题: 使用splice删除数组中的某一项后, 删除这一项后面的每一项索引都要向前进一位(在原有索引上减一) 92 | // 此时如果我们j++ 循环操作的值累加了,我们通过最新j获取的元素不是紧挨删除这一项的元素,而是跳过了这一项的元素; 93 | ``` 94 | ```javascript 95 | // 思路二 96 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 97 | for(var i=0;i [1, 2, 3, 5, 4] 109 | ``` 110 | ```javascript 111 | // 思路三 112 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 113 | for(var i=0;i [1, 2, 3, 5, 4] 124 | 125 | // 循环判断可以达到数组去重的结果 126 | // 但是由于循环操作的重复性,在达到一定数量级以后,会造成严重的性能问题 127 | ``` 128 | 129 | - 方案二: indexOf方法去重 130 | 131 | ```javascript 132 | // 利用indexOf实现数组去重(不兼容ie6~8) 133 | // 检验数组中除去当前项意外是否包含当前项,如果存在就删除,否则保留 134 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 135 | for(var i=0;i -1){ 139 | // 后面项组成的数组中包含当前项(当前项重复了), 我们把当前这一项删除掉即可 140 | ary.splice(i,1); 141 | i--; 142 | } 143 | } 144 | console.log(ary) // -> [1, 3, 4, 5, 2] 145 | 146 | // 方案一的方法是从前往后遍历, 所以结果保留从前往后出现的元素 147 | 148 | // 方案二的方法使从前往后删除已存在的元素,所以结果保留从后往前的出现的元素 149 | ``` 150 | 151 | - 对象键值对处理 152 | 153 | ```javascript 154 | // 遍历数组中的每一项,把每一项作为新对象的属性名和属性值存储起来, 155 | // 例如当前项1,对象中存储的{1:1} 156 | 157 | // 在每一次向对象中存储之前,首先看一下原有对象中是否包含了这个属性 158 | // ('typeof obj[xxx] === 'undefined' 说明当前对象中没有 xxx 这个属性) 159 | // 如果已经存在这个属性说明数组中的当前项重复了 160 | // (1. 在原有数组中删除这一项;2. 不再向对象中存储这个结果) 161 | // 如果不存在(把当前项作为对象的属性名和属性值存储进来即可) 162 | 163 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 164 | var obj = {}; 165 | for(var i=0;i [1, 2, 3, 5, 4] 176 | ``` 177 | ```javascript 178 | var ary = [1,2,2,2,3,3,3,1,5,3,4,5,2,4,5,2]; 179 | var obj = {}; 180 | for(var i=0;i [1, 2, 5, 4, 3] 194 | ``` 195 | ```javascript 196 | Array.prototype.myUnique = function myUnique(){ 197 | var obj = {}; 198 | for(var i=0;i [1, 2, 5, 4, 3] 213 | console.log(ary.myUnique().sort(function(a,b){return a-b})) // -> [1, 2, 5, 4, 3] 214 | ``` 215 | 216 | **方案一,二,三都实现了数组去重,但方案一性能差,方案二兼容差,所以方案三为最优解** 217 | 218 | - 其他思路扩展 219 | 220 | 1. 相邻比较法 221 | 222 | > 首先给数组进行排序,然后给相邻两项比较,相同的话,删除后一项 223 | -------------------------------------------------------------------------------- /javascriptLearnLog/README.md: -------------------------------------------------------------------------------- 1 | ### 本套笔记是根据 `B站` [珠峰培训 Javascript 部分(一)](https://www.bilibili.com/video/av18051052) [珠峰培训 Javascript 部分(二)](https://www.bilibili.com/video/av18045240) 学习整理 2 | 3 | #### 笔记同步收录在我的 `简书` [js笔记](https://www.jianshu.com/c/95363e23b463) 专题里   4 | 我的简书 [主页](https://www.jianshu.com/u/04a926aaa55c) 5 | 6 | 1. [js笔记一之初识JS](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%80%E4%B9%8B%E5%88%9D%E8%AF%86JS.md) 7 | 2. [js笔记二之数据类型](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.md) 8 | 3. [js笔记三之布尔(Boolean),字符串(String),null和undefined](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E4%B9%8B%E5%B8%83%E5%B0%94(Boolean)%2C%E5%AD%97%E7%AC%A6%E4%B8%B2(String)%2Cnull%E5%92%8Cundefined.md) 9 | 4. [js笔记四之数字(Number)类型](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E4%B9%8B%E6%95%B0%E5%AD%97(Number)%E7%B1%BB%E5%9E%8B.md) 10 | 5. [js笔记五之对象(object)类型](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%94%E4%B9%8B%E5%AF%B9%E8%B1%A1(object)%E7%B1%BB%E5%9E%8B.md) 11 | 6. [js笔记六之基本数据类型和引用数据类型的区别](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%85%AD%E4%B9%8B%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB.md) 12 | 7. [js笔记七之函数初步了解](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%83%E4%B9%8B%E5%87%BD%E6%95%B0%E5%88%9D%E6%AD%A5%E4%BA%86%E8%A7%A3.md) 13 | 8. [js笔记八之if-else if-else判断语句,三元运算符,switch case判断语句](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%85%AB%E4%B9%8Bif-else%20if-else%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5%2C%E4%B8%89%E5%85%83%E8%BF%90%E7%AE%97%E7%AC%A6%2Cswitch%20case%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5.md) 14 | 9. [js笔记九之for,for-in循环](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B9%9D%E4%B9%8Bfor%2Cfor-in%E5%BE%AA%E7%8E%AF.md) 15 | 10. [js笔记十之for循环练习](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%B9%8Bfor%E5%BE%AA%E7%8E%AF%E7%BB%83%E4%B9%A0.md) 16 | 11. [js笔记十一之数据类型转换](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%B8%80%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.md) 17 | 12. [js笔记十二之Math数学函数](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%BA%8C%E4%B9%8BMath%E6%95%B0%E5%AD%A6%E5%87%BD%E6%95%B0.md) 18 | 13. [js笔记十三之字符串及常用方法](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%B8%89%E4%B9%8B%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%8A%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95.md) 19 | 14. [js笔记十四之Math和字符串方法应用](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E5%9B%9B%E4%B9%8BMath%E5%92%8C%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%96%B9%E6%B3%95%E5%BA%94%E7%94%A8.md) 20 | 15. [js笔记十五之DOM基础-获取元素的方法](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%BA%94%E4%B9%8BDOM%E5%9F%BA%E7%A1%80-%E8%8E%B7%E5%8F%96%E5%85%83%E7%B4%A0%E7%9A%84%E6%96%B9%E6%B3%95.md) 21 | 16. [js笔记十六之DOM基础-节点](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E5%85%AD%E4%B9%8BDOM%E5%9F%BA%E7%A1%80-%E8%8A%82%E7%82%B9.md) 22 | 17. [js笔记十七之DOM操作-增删改](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%B8%83%E4%B9%8BDOM%E6%93%8D%E4%BD%9C-%E5%A2%9E%E5%88%A0%E6%94%B9.md) 23 | 18. [js笔记十八之Date日期](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E5%85%AB%E4%B9%8BDate%E6%97%A5%E6%9C%9F.md) 24 | 19. [js笔记十九之Array数组的增删改](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%8D%81%E4%B9%9D%E4%B9%8BArray%E6%95%B0%E7%BB%84%E7%9A%84%E5%A2%9E%E5%88%A0%E6%94%B9.md) 25 | 20. [js笔记二十之Array数组的查询,拼接,转字符串,排列(序)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%B9%8BArray%E6%95%B0%E7%BB%84%E7%9A%84%E6%9F%A5%E8%AF%A2%2C%E6%8B%BC%E6%8E%A5%2C%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%2C%E6%8E%92%E5%88%97(%E5%BA%8F).md) 26 | 21. [js笔记二十一Array数组检查,遍历,去重](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%B8%80Array%E6%95%B0%E7%BB%84%E6%A3%80%E6%9F%A5%2C%E9%81%8D%E5%8E%86%2C%E5%8E%BB%E9%87%8D.md) 27 | 22. [js笔记二十二之数组排序算法-冒泡,递归,快速,插入](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%BA%8C%E4%B9%8B%E6%95%B0%E7%BB%84%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95-%E5%86%92%E6%B3%A1%2C%E9%80%92%E5%BD%92%2C%E5%BF%AB%E9%80%9F%2C%E6%8F%92%E5%85%A5.md) 28 | 23. [js笔记二十三之函数的操作](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%B8%89%E4%B9%8B%E5%87%BD%E6%95%B0%E7%9A%84%E6%93%8D%E4%BD%9C.md) 29 | 24. [js笔记二十四之函数的形参与实参](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E5%9B%9B%E4%B9%8B%E5%87%BD%E6%95%B0%E7%9A%84%E5%BD%A2%E5%8F%82%E4%B8%8E%E5%AE%9E%E5%8F%82.md) 30 | 25. [js笔记二十五之函数中的return及匿名函数](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%BA%94%E4%B9%8B%E5%87%BD%E6%95%B0%E4%B8%AD%E7%9A%84return%E5%8F%8A%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0.md) 31 | 26. [js笔记二十六之预解释](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E5%85%AD%E4%B9%8B%E9%A2%84%E8%A7%A3%E9%87%8A.md) 32 | 27. [js笔记二十七之预解释的特殊处理及上级作用域](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%B8%83%E4%B9%8B%E9%A2%84%E8%A7%A3%E9%87%8A%E7%9A%84%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86%E5%8F%8A%E4%B8%8A%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F.md) 33 | 28. [js笔记二十八之内存释放与作用域销毁](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E5%85%AB%E4%B9%8B%E5%86%85%E5%AD%98%E9%87%8A%E6%94%BE%E4%B8%8E%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%94%80%E6%AF%81.md) 34 | 29. [js笔记二十九之this关键字](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%BA%8C%E5%8D%81%E4%B9%9D%E4%B9%8Bthis%E5%85%B3%E9%94%AE%E5%AD%97.md) 35 | 30. [js笔记三十之单例模式和工厂模式](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%B9%8B%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%92%8C%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.md) 36 | 31. [js笔记三十一之构造函数模式基础](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%B8%80%E4%B9%8B%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%A8%A1%E5%BC%8F%E5%9F%BA%E7%A1%80.md) 37 | 32. [js笔记三十二之构造函数模式扩展](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%BA%8C%E4%B9%8B%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%A8%A1%E5%BC%8F%E6%89%A9%E5%B1%95.md) 38 | 33. [js笔记三十三之原型链模式基础](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%B8%89%E4%B9%8B%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%A8%A1%E5%BC%8F%E5%9F%BA%E7%A1%80.md) 39 | 34. [js笔记三十四之原型链模式扩展(1)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E5%9B%9B%E4%B9%8B%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%A8%A1%E5%BC%8F%E6%89%A9%E5%B1%95(1).md) 40 | 35. [js笔记三十五之原型链模式扩展(2)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%BA%94%E4%B9%8B%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%A8%A1%E5%BC%8F%E6%89%A9%E5%B1%95(2).md) 41 | 36. [js笔记三十六之原型链模式扩展(3)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E5%85%AD%E4%B9%8B%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%A8%A1%E5%BC%8F%E6%89%A9%E5%B1%95(3).md) 42 | 37. [js笔记三十七之函数的三种角色](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%B8%83%E4%B9%8B%E5%87%BD%E6%95%B0%E7%9A%84%E4%B8%89%E7%A7%8D%E8%A7%92%E8%89%B2.md) 43 | 38. [js笔记三十八之call方法深入](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E5%85%AB%E4%B9%8Bcall%E6%96%B9%E6%B3%95%E6%B7%B1%E5%85%A5.md) 44 | 39. [js笔记三十九之call,apply和bind的区别](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E4%B8%89%E5%8D%81%E4%B9%9D%E4%B9%8Bcall%2Capply%E5%92%8Cbind%E7%9A%84%E5%8C%BA%E5%88%AB.md) 45 | 40. [js笔记四十获取数组中的最大值和最小值(四种方法)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E8%8E%B7%E5%8F%96%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E5%80%BC%E5%92%8C%E6%9C%80%E5%B0%8F%E5%80%BC(%E5%9B%9B%E7%A7%8D%E6%96%B9%E6%B3%95).md) 46 | 41. [js笔记四十一类数组转换为数组(浏览器异常捕获)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E4%B8%80%E7%B1%BB%E6%95%B0%E7%BB%84%E8%BD%AC%E6%8D%A2%E4%B8%BA%E6%95%B0%E7%BB%84(%E6%B5%8F%E8%A7%88%E5%99%A8%E5%BC%82%E5%B8%B8%E6%8D%95%E8%8E%B7).md) 47 | 42. [js笔记四十二之sort深入研究](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E4%BA%8C%E4%B9%8Bsort%E6%B7%B1%E5%85%A5%E7%A0%94%E7%A9%B6.md) 48 | 43. [js笔记四十三之json操作及DOM回流](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E4%B8%89%E4%B9%8Bjson%E6%93%8D%E4%BD%9C%E5%8F%8ADOM%E5%9B%9E%E6%B5%81.md) 49 | 44. [js笔记四十四之表格排序,DOM映射及初识ajax](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E5%9B%9B%E4%B9%8B%E8%A1%A8%E6%A0%BC%E6%8E%92%E5%BA%8F%2CDOM%E6%98%A0%E5%B0%84%E5%8F%8A%E5%88%9D%E8%AF%86ajax.md) 50 | 45. [js笔记四十五之正则表达式(1)](https://github.com/uplyw/Learning_records/blob/master/javascriptLearnLog/js%E7%AC%94%E8%AE%B0%E5%9B%9B%E5%8D%81%E4%BA%94%E4%B9%8B%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F(1).md) 51 | --------------------------------------------------------------------------------