├── README.md ├── AJAX工作原理.pdf ├── JS的原型和原型链.pdf ├── React学习资源汇总.pdf ├── ionic初学者填坑.docx ├── ionic初学者填坑.pdf ├── windowName跨域详解.pdf ├── 事件绑定、事件监听、事件委托.pdf ├── Arguments对象作用深度研究.pdf ├── JavaScript中this指向.docx ├── JavaScript中this指向.pdf ├── JavaScript闭包(closure).pdf ├── 模仿知乎界面的一个简单React demo.pdf ├── JS中的call、apply、bind方法详解.pdf ├── 各阶段前端工程师都应该具备什么能力(JS篇).pdf ├── 折腾:coding IDE node环境安装.pdf ├── html5 API postMessage跨域详解.pdf ├── 深入了解JavaScript,从作用域链开始(1).pdf ├── 深入了解JavaScript,优化作用域链(2).pdf ├── 折腾:coding.net IDE node环境的安装.md ├── html5 API postMessage跨域详解.md ├── 模仿知乎界面的一个简单React demo.md ├── windowName跨域详解.md ├── 各阶段前端工程师都应该具备什么能力(JS篇).md ├── 深入了解JavaScript,优化作用域链(2).md ├── Arguments对象作用深度研究.md ├── AJAX工作原理.md ├── JS中的call、apply、bind方法详解.md ├── JavaScript中this指向.md ├── JavaScript闭包(closure).md ├── 深入了解JavaScript,从作用域链开始(1).md ├── JS的原型和原型链.md ├── React学习资源汇总.md └── 事件绑定、事件监听、事件委托.md /README.md: -------------------------------------------------------------------------------- 1 | # Study-Notes 2 | 3 | 前端开发的一些学习笔记和感悟 4 | -------------------------------------------------------------------------------- /AJAX工作原理.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/AJAX工作原理.pdf -------------------------------------------------------------------------------- /JS的原型和原型链.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/JS的原型和原型链.pdf -------------------------------------------------------------------------------- /React学习资源汇总.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/React学习资源汇总.pdf -------------------------------------------------------------------------------- /ionic初学者填坑.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/ionic初学者填坑.docx -------------------------------------------------------------------------------- /ionic初学者填坑.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/ionic初学者填坑.pdf -------------------------------------------------------------------------------- /windowName跨域详解.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/windowName跨域详解.pdf -------------------------------------------------------------------------------- /事件绑定、事件监听、事件委托.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/事件绑定、事件监听、事件委托.pdf -------------------------------------------------------------------------------- /Arguments对象作用深度研究.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/Arguments对象作用深度研究.pdf -------------------------------------------------------------------------------- /JavaScript中this指向.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/JavaScript中this指向.docx -------------------------------------------------------------------------------- /JavaScript中this指向.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/JavaScript中this指向.pdf -------------------------------------------------------------------------------- /JavaScript闭包(closure).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/JavaScript闭包(closure).pdf -------------------------------------------------------------------------------- /模仿知乎界面的一个简单React demo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/模仿知乎界面的一个简单React demo.pdf -------------------------------------------------------------------------------- /JS中的call、apply、bind方法详解.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/JS中的call、apply、bind方法详解.pdf -------------------------------------------------------------------------------- /各阶段前端工程师都应该具备什么能力(JS篇).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/各阶段前端工程师都应该具备什么能力(JS篇).pdf -------------------------------------------------------------------------------- /折腾:coding IDE node环境安装.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/折腾:coding IDE node环境安装.pdf -------------------------------------------------------------------------------- /html5 API postMessage跨域详解.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/html5 API postMessage跨域详解.pdf -------------------------------------------------------------------------------- /深入了解JavaScript,从作用域链开始(1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/深入了解JavaScript,从作用域链开始(1).pdf -------------------------------------------------------------------------------- /深入了解JavaScript,优化作用域链(2).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsrot/study-notes/HEAD/深入了解JavaScript,优化作用域链(2).pdf -------------------------------------------------------------------------------- /折腾:coding.net IDE node环境的安装.md: -------------------------------------------------------------------------------- 1 | # 折腾:coding.net IDE node环境的安装 2 | 3 | 地址:http://blog.xieliqun.com/2016/08/27/online-IDE-node-enviroment/ 4 | 5 | > 作为一个码农,我们经常会有这样一个痛点:项目出现一个紧急bug,但自己又不在公司,怎办呢?虽然项目可能在git或者svn上,但clone下来安装测试环境也是个麻烦的是啊。于是,我们想到了在线IDE。作为一个前端开发者nodeJS环境是非常重要的,今天花了一个多小时折腾了下[coding.net](https://ide.coding.net)。 6 | 7 | 8 | ---------- 9 | 10 | ### IDE介绍 11 | 12 | 以前我一直在用[nitrous.io](https://nitrous.io)的在线IDE,它是一个国外的在线IDE,访问有点慢,一旦网络不好就掉线,挺好的地方就是,它每个月有50个小时的免费使用。coding.net相当于是一个国内版的github,也是一个远程的git仓库,它有个在线IDE还挺好用的。有终端命令面板、支持vim和 Emacs的编辑器、在线运行环境、支持git(哎,帮别人做广告了,不知道coding能不能发我点稿费)。 13 | 14 | 下面进入主题。 15 | 16 | 17 | ### 安装nvm 18 | 19 | nvm是nodejs版本管理工具。可以在多个nodejs版本中进行切换,降低了升级nodejs时的成本。 20 | 21 | 下载nvm,直接在终端面板把它clone过来就行了。为了不影响项目目录,我们把它clone在项目根目录的同级目录。 22 | ```bash 23 | -> ~ cd .. 24 | -> ~ git clone https://github.com/creationix/nvm.git 25 | ``` 26 | 27 | 接下来,进入nvm目录 28 | ```bash 29 | -> ~ cd nvm 30 | ``` 31 | 32 | 安装nvm 33 | ```bash 34 | -> ~ ./install.sh 35 | ``` 36 | 37 | 安装完后,让系统自动执行它 38 | ```bash 39 | -> ~ source ./nvm.sh 40 | ``` 41 | 42 | 现在就可以使用nvm命令了,查看一下help 43 | ```bash 44 | -> ~ nvm -help 45 | ``` 46 | 47 | 48 | ### 安装nodeJS 49 | 50 | 查看可以安装的nodejs版本,这里将会输出一大堆可供安装的nodejs版本 51 | ```bash 52 | -> ~ nvm ls-remote 53 | ``` 54 | 55 | 选择一个进行安装,我安装的是v4.5.0 56 | ```bash 57 | -> ~ nvm install v4.5.0 58 | ``` 59 | 60 | 当然你可以安装多个版本,例如我还要安装最新版本,测试一下它的新特性 61 | ```bash 62 | -> ~ nvm install v6.4.0 63 | ``` 64 | 65 | 当你想切换回原先稳定版本时,你可以 66 | ```bash 67 | -> ~ nvm use v4.5.0 68 | ``` 69 | 70 | 安装完node,你就可以使用node和npm了。你可以安装一些自动化工具啊,一些插件啊什么的。 71 | 72 | 73 | ### 一些问题 74 | 75 | 1、这些在线IDE虽然挺方便的,但毕竟没有本地的好,还有一些安全和网络限制的问题,另外到后面可能还要收费。 76 | 77 | 2、nvm问题,因为coding没有给用户root权限,所以你每次要运行node前都必须运行一下nvm。 78 | 79 | ```bash 80 | -> ~ cd .. 81 | -> ~ cd nvm 82 | -> ~ source ./nvm.sh 83 | ``` 84 | 85 | ### END -------------------------------------------------------------------------------- /html5 API postMessage跨域详解.md: -------------------------------------------------------------------------------- 1 | # html5 API postMessage跨域详解 2 | 3 | @(我的第一个笔记本)[postMessage, 跨域] 4 | 5 | 地址:http://blog.xieliqun.com/2016/08/25/postMessage-cross-domain/ 6 | 7 | > window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。 8 | 9 | 10 | ---------- 11 | 12 | ### 准备 13 | 14 | 跨域是什么,我就不详细解释了,我相信你在看这篇文章前就已经了解的差不多了。现在我就直接进入实战阶段。 15 | 16 | **两个服务器**: 17 | - http://127.0.0.1:8080 18 | - http://127.0.0.1:9090 19 | 20 | 先建立两个不同域的测试环境。我用http-server(一个node服务器插件)建立了两个不同端口的本地服务器。 21 | 22 | **两个页面**: 23 | - a.html 24 | - b.html 25 | 26 | 在http://127.0.0.1:8080中新建a.html,在http://127.0.0.1:9090中新建b.html。 27 | 28 | ### 数据发送 29 | 30 | postMessage允许用户在两个窗口或frame之间传递数据,无论这个window对象是不是同源都能发送。 31 | 32 | 首先我们先在a.html中建立一个iframe。 33 | 34 | ```javascript 35 | 36 | ``` 37 | 38 | 当iframe加载完时,发送数据 39 | 40 | ```javascript 41 | function messageLoad(){ 42 | 43 | var url = "http://127.0.0.1:9090"; 44 | 45 | window.postIframe.postMessage("给我tsort的信息",url); 46 | 47 | } 48 | ``` 49 | 50 | postMessage包括两个参数data和url,data为发送的数据,url为发送地址。 51 | 52 | 53 | ### 数据接收 54 | 55 | html5新增了onmessage事件,它和onclick之类用法差不多。当窗口或frame接收到postMessage发送过来的数据时,将触发onmessage事件。 56 | 57 | ```javascript 58 | window.onmessage = function(e){ 59 | e = e || event; 60 | alert(e.data); 61 | } 62 | ``` 63 | 64 | 该事件接收一个event对象,这个对象有三个属性,分别为source,origin,data。 65 | 66 | **source**: 消息源,消息的发送窗口/iframe。 67 | **origin**:消息源的URI(可能包含协议、域名和端口),用来验证数据源。 68 | **data**:发送方发送给接收方的数据。 69 | 70 | ### 完整例子 71 | 72 | 这个例子是这样的,a页面中有一个iframe,这个iframe是另一个域的b页面。当b加载完的时候,让它去给iframe里的页面发送一条信息。然后里面的页面立即回复已经接收到信息,然后再等三秒,回复a所请求的数据。 73 | 74 | a.html 75 | 76 | ```javascript 77 | 78 | 79 | 80 | 81 | Document 82 | 83 | 84 | 85 | 86 | 87 | 98 | 99 | 100 | ``` 101 | 102 | b.html 103 | 104 | ```javascript 105 | 106 | 107 | 108 | 109 | Document 110 | 111 | 112 | 125 | 126 | 127 | ``` 128 | -------------------------------------------------------------------------------- /模仿知乎界面的一个简单React demo.md: -------------------------------------------------------------------------------- 1 | # 模仿知乎界面的一个简单React demo 2 | 3 | 博客地址:http://blog.xieliqun.com/2016/11/04/react-zhihu/ 4 | 5 | 6 | 7 | > 这是一个模仿知乎界面的简单React demo。这个React demo能让你从零开始学习React,并逐渐掌握React。它包括了一个项目从零到项目完成的整个过程。 8 | 9 | 项目地址:[https://github.com/tsrot/react-zhihu](https://github.com/tsrot/react-zhihu) 10 | 项目预览:[http://blog.xieliqun.com/react-zhihu/](http://blog.xieliqun.com/react-zhihu/) 11 | 12 | **项目运行** 13 | ```javascript 14 | $ git clone https://github.com/tsrot/react-zhihu.git 15 | $ cd react-zhihu 16 | 17 | $ npm install 18 | 19 | $ bower install 20 | 21 | $ gulp server //用浏览器打开 localhost:5000 22 | ``` 23 | 24 | 25 | ## 搭建开发环境 26 | 27 | ### 初始化npm bower 28 | 29 | ```javascript 30 | npm init //一直enter,默认就好 31 | 32 | bower init //同上 33 | 34 | ``` 35 | 36 | ### 安装必要的开发工具包 37 | 38 | - gulp :基于流的自动化构建工具 39 | - gulp-browserify :前端模块及依赖管理 40 | - gulp-concat :文件合并插件 41 | - gulp-react :JSX语法转化工具 42 | - gulp-connect :构建本地开发Web服务器 43 | - lodash :一个具有一致接口、模块化、高性能等特性的 JavaScript 工具库 44 | - reactify :React 编译器 45 | 46 | ```javascript 47 | npm install gulp gulp-browserify gulp-concat gulp-react gulp-connect lodash reactify --save-dev 48 | ``` 49 | 50 | ### 安装生产环境依赖包 51 | 52 | - react :主要框架 53 | - react-dom :React的DOM操作类 54 | - bootstrap :bootstrap样式 55 | 56 | ```javascript 57 | npm install --save react react-dom 58 | 59 | bower install --save bootstrap 60 | ``` 61 | 62 | ### 写入gulp配置文件gulpfile.js 63 | 64 | 你可以在npm的网站上找到相应插件的gulp配置写法。我配置的[gulpfile.js](https://github.com/tsrot/) 65 | 66 | 67 | ## 开发 68 | 69 | - 切分相应的模块 70 | - 分清UI组件和容器组件 71 | - 学会如何在组件之间通信 72 | - 注意写作规范和开发细节 73 | 74 | ## 部署生产 75 | 76 | 请切换分支到 product 分支 77 | 78 | ### 修改gulpfile文件 79 | ```javascript 80 | //添加copy任务 81 | gulp.task('copy',function(){ 82 | gulp.src('./app/css/*') 83 | .pipe(gulp.dest('./dist/css')); 84 | 85 | gulp.src('./bower_components/**/*') 86 | .pipe(gulp.dest('./dist/libs')); 87 | 88 | gulp.src('./*.html') 89 | .pipe(gulp.dest('./dist')); 90 | }); 91 | 92 | //生产服务器 93 | gulp.task('connect-pro',function(){ 94 | connect.server({ 95 | root:'./dist', 96 | port:port, 97 | livereload:true, 98 | }) 99 | }); 100 | 101 | //添加build任务 102 | gulp.task('build',['browserify','copy']); 103 | 104 | //添加启动生产服务器任务 105 | gulp.task('server-pro',['build','connect-pro','watch']); 106 | ``` 107 | 108 | ### 修改index.html引用目录 109 | ```javascript 110 | 111 | 112 | 113 | 114 | ``` 115 | 116 | ### 使用gulp-gh-pages部署到github pages 117 | 118 | 下载gulp-gh-pages插件 119 | ```javascript 120 | npm install --save-dev gulp-gh-pages 121 | ``` 122 | 在gulpfile文件中添加配置gulp-gh-pages代码 123 | ```javascript 124 | var ghPages = require('gulp-gh-pages'); 125 | 126 | gulp.task('deploy', function() { 127 | return gulp.src('./dist/**/*') 128 | .pipe(ghPages()); 129 | }); 130 | ``` 131 | 132 | ## 后续 133 | 134 | 将在分支中更新使用下列技术的版本 135 | - webpack 136 | - webpack + redux 137 | - webkack + redux + react-router -------------------------------------------------------------------------------- /windowName跨域详解.md: -------------------------------------------------------------------------------- 1 | # window.name跨域详解 2 | 3 | @(github.com/tsrot)[window.name|跨域] 4 | 5 | 地址:http://blog.xieliqun.com/2016/08/25/windowName-cross-domain/ 6 | 7 | > window.name属性的神奇之处在于name 值在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)。并且window.name很方便。 8 | 9 | 10 | ---------- 11 | 12 | ### 用法介绍 13 | 14 | name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面(可以是不同域的)时,name 的属性值依旧保持不变(只要不重新赋值)。name属性的值虽然不变,但对它的访问还是受到同域原则,不允许访问。所以我们要把iframe重新定向回原域,这样name的值也没变,并且可以访问了。 15 | 16 | 在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。 17 | 18 | 19 | ### 函数封装 20 | 21 | 为了方便以后的使用,我们把window.name进行一下封装。 22 | 23 | ```javascript 24 | function proxy(url, func){ 25 | var isFirst = true,//判断url第一次是否加载完 26 | ifr = document.createElement('iframe'), 27 | loadFunc = function(){ 28 | if(isFirst){ 29 | //加载完url后,重新定向回原域 30 | ifr.contentWindow.location = 'about:blank'; 31 | isFirst = false; 32 | }else{ 33 | //iframe回到原域后,获取name的值,执行回调函数,然后销毁iframe 34 | func(ifr.contentWindow.name); 35 | ifr.contentWindow.close(); 36 | document.body.removeChild(ifr); 37 | ifr.src = ''; 38 | ifr = null; 39 | } 40 | }; 41 | 42 | ifr.src = url; //第一次加载url 43 | ifr.style.display = 'none'; 44 | document.body.appendChild(ifr); 45 | 46 | //监听iframe是否加载,加载完执行loadFunc 47 | if(ifr.attachEvent){ 48 | ifr.attachEvent('onload', loadFunc); 49 | }else{ 50 | ifr.onload = loadFunc; 51 | } 52 | 53 | } 54 | ``` 55 | 56 | 57 | ### 详细案例 58 | 59 | 假设我现在在http://127.0.0.1:8080 ,我有一个页面叫做a.html,现在我想获取http://127.0.0.1:9090 上的b.html的数据。 60 | 61 | a.html 62 | ```javascript 63 | 64 | 65 | 66 | 95 | 96 | 97 | 103 | 104 | 105 | ``` 106 | 107 | b.html 108 | ```javascript 109 | 110 | 111 | 112 | 113 | Document 114 | 115 | 116 | 123 | 124 | 125 | ``` -------------------------------------------------------------------------------- /各阶段前端工程师都应该具备什么能力(JS篇).md: -------------------------------------------------------------------------------- 1 | # 各阶段前端工程师都应该具备什么能力(JS篇) 2 | 3 | 4 | > 作为一名程序猿、攻城狮,要清楚自己的实力,自己所处的阶段,这样才能更好的扬长补短。常问自己几个问题:我最擅长什么,我比别人有哪些优势?我的短板在哪些方面?我在整个行业所处什么阶段,在这个阶段我该如何提升自己? 5 | > 对于前端工程师等级的划分,每个人都可能有自己的理解,正所谓,一千个读者就有一千个哈姆雷特。下面是我对前端工程师划分的一些拙见。 6 | 7 | ## 一、入门菜鸟 8 | 9 | 这个阶段一般具备以下几点: 10 | - 基础的JavaScript编程能力 11 | - 基本能看懂别人写的代码 12 | - 有一定的代码调试能力 13 | 14 | 举些例子: 15 | ### 1、怎样对字符串进行截取操作,你会想到哪些方法? 16 | substr() ,sibString(), split(), slice() ... 17 | 18 | ### 2、给你一段代码,你能知道这段代码实现了什么功能,别人为什么要这么写? 19 | ```javascript 20 | var url = window.location.href; 21 | if(url === 'http://www.xieliqun.com'){ 22 | window.location.href = 'https://github.com/tsrot'; 23 | }else{ 24 | window.location.href = '/404'; 25 | } 26 | ``` 27 | ### 3、给你一段简单的错误代码,你能知道错在哪里,怎样去改正它? 28 | ```javascript 29 | var foo = 'hello world!'; 30 | var arr = []; 31 | for(var i=0;i 作为一个良好的开发者必需考虑程序的运行性能,作用域链的层级关系是JavaScript性能优化的一个重要部分。因为这关系到变量在内存里的读写速度。 6 | 7 | 8 | ---------- 9 | 10 | ### 尽量使用局部变量 11 | 12 | 从作用域链的结构可以看出,在执行上下文的作用域链中,标识符所在的位置越深,读写速度就会越慢。 13 | 14 | 全局变量总是存在于执行上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量是最慢的,并且全局变量将常驻内存直到程序退出,而局部变量会在函数运行完直接销毁。所以,在编写代码的时候应尽量少使用全局变量,尽可能使用局部变量。 15 | 16 | 一个好的经验法则是:如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。例如: 17 | ```javascript 18 | function toggle(){ 19 | if(document.getElementById('btn').className == 'active'){ 20 | document.getElementById('btn').className = ''; 21 | //do someThing 22 | }else{ 23 | document.getElementById('btn').className = 'active'; 24 | //do someThing 25 | } 26 | } 27 | ``` 28 | 以上代码中`document.getElementById('btn').className`被引用了三次,查找该变量必须遍历整个作用域链,直到最后在全局对象中才能找到`document`,然后再去找它的方法和属性,这样严重的影响了程序性能。我们可以改为: 29 | ```javascript 30 | function toggle(){ 31 | var btnClass = document.getElementById('btn').className; 32 | if(btnClass == 'active'){ 33 | btnClass = ''; 34 | //do someThing 35 | }else{ 36 | btnClass = 'active'; 37 | //do someThing 38 | } 39 | } 40 | ``` 41 | 42 | ### 尽量不要改变作用域链 43 | 44 | 函数每次执行时对应的执行上下文都是独一无二的,所以多次调用同一个函数就会导致创建多个执行上下文,当函数执行完毕,执行上下文会被销毁。每一个执行上下文都和一个作用域链关联。一般情况下,在执行上下文运行的过程中,其作用域链只会被 with 语句和 catch 语句影响。 45 | 46 | with语句是对象的快捷应用方式,用来避免书写重复代码。例如: 47 | ```javascript 48 | var o = {href:"github.com"}; 49 | var href = "blog.xieliqun.com"; 50 | 51 | function buildUrl(){ 52 | var q = "?name=tsrot"; 53 | with(o){ 54 | var url = href+q; 55 | } 56 | return url; 57 | } 58 | 59 | var result = buildUrl(); 60 | alert(result); //github.com?name=tsrot 61 | alert(href); //blog.xieliqun.com 62 | ``` 63 | 第一个alert使用的o对象里的href,所以弹出github.com?name=tsrot,第二个alert使用的就是全局的href。 64 | 65 | 当代码运行到with语句时,运行期上下文的作用域链临时被改变了。一个新的可变对象被创建,它包含了参数指定的对象的所有属性。这个对象将被推入作用域链的头部,这意味着函数的所有局部变量现在处于第二个作用域链对象中,因此访问代价更高了。此时的作用域链为: 66 | ```flow 67 | 68 | scope -> with.AO -> with.VO -> buildUrl.AO -> Global Object 69 | 70 | with.AO = { 71 | url : undefined 72 | } 73 | 74 | with.VO = { 75 | href : "github.com" 76 | } 77 | 78 | buildUrl.AO = { 79 | q : "?name=tsrot" 80 | } 81 | 82 | Global Object = { 83 | o : {href:"github.com"}, 84 | href : "blog.xieliqun.com", 85 | buildUrl : , 86 | result : undefined 87 | } 88 | ``` 89 | 另外一个会改变作用域链的是try-catch语句中的catch语句。当try代码块中发生错误时,执行过程会跳转到catch语句,然后把异常对象推入一个可变对象并置于作用域的头部。在catch代码块内部,函数的所有局部变量将会被放在第二个作用域链对象中。 90 | 91 | 92 | ### 闭包问题 93 | 94 | 一个函数只要内部函数未销毁(内部函数存在被调用的可能),这个函数就不会销毁,将一直存在于内存中,只有所有内部函数都销毁了,并所有的业务代码都已执行完,这个函数才会被释放。我们看看最常见的闭包问题: 95 | ```javascript 96 | function show(){ 97 | var li = document.getElementsByTagName('li'); 98 | var length = li.length; 99 | for(var i=0;i 每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。 8 | 9 | 10 | ---------- 11 | 12 | ### Arguments对象介绍 13 | 14 | Arguments对象是一个伪数组对象,它有length属性,可以arguments[i]来访问对象中的元素,但它不能用数组的一些方法,例如push,pop,slice等。 15 | 16 | #### Arguments的length属性 17 | 18 | Arguments的length属性,表示function函数实际所传参数的个数。函数名点length可以获取函数期望的传参个数。 19 | 20 | ```javascript 21 | function argTest(a,b,c){ 22 | var t = arguments.length; //实际传参个数 23 | var e = argTest.length; //期望传参个数 24 | 25 | console.log(t); 26 | console.log(e); 27 | } 28 | 29 | argTest(11,12); //t=2,e=3 30 | argTest(11,12,13); //t=3,e=3 31 | argTest(11,12,13,14); //t=4,e=3 32 | ``` 33 | 34 | 35 | #### Arguments的参数访问 36 | 37 | Arguments对象的参数访问可以用arguments[i]来访问函数所传的参数。 38 | 39 | ```javascript 40 | function argTest(a,b,c){ 41 | var arg = []; 42 | for(var i=0;i maxNum){ 179 | maxNum = arguments[i]; 180 | } 181 | } 182 | return maxNum; 183 | } 184 | 185 | max(1,2,3,11,4,10); //11 186 | max(2,-10,22,11); //22 187 | ``` -------------------------------------------------------------------------------- /AJAX工作原理.md: -------------------------------------------------------------------------------- 1 | # AJAX工作原理 2 | 3 | @(github.com/tsrot)[AJAX|] 4 | 5 | 地址:http://blog.xieliqun.com/2016/08/08/ajax/ 6 | 7 | 8 | > AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 9 | 10 | 11 | ---------- 12 | ### 一、ajax所包含的技术 13 | 大家都知道ajax并非一种新的技术,而是几种原有技术的结合体。它由下列技术组合而成。 14 | - 使用CSS和XHTML来表示。 15 | - 使用DOM模型来交互和动态显示。 16 | - 使用XMLHttpRequest来和服务器进行异步通信。 17 | - 使用javascript来绑定和调用。 18 | 19 | 在上面几中技术中,除了XmlHttpRequest对象以外,其它所有的技术都是基于web标准并且已经得到了广泛使用的,XMLHttpRequest虽然目前还没有被W3C所采纳,但是它已经是一个事实的标准,因为目前几乎所有的主流浏览器都支持它。 20 | 21 | ### 二、怎样创建ajax 22 | 23 | Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。原生创建ajax可分为以下四步。 24 | 25 | #### 1、创建XMLHttpRequest对象 26 | 所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。 27 | 创建 XMLHttpRequest 对象的语法: 28 | ```javascript 29 | var xhr = new XMLHttpRequest(); 30 | ``` 31 | 老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象: 32 | ```javascript 33 | var xhr = new ActiveXObject("Microsoft.XMLHTTP"); 34 | ``` 35 | 为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象。如果不支持,则创建 ActiveXObject : 36 | ```javascript 37 | var xhr; 38 | if(XMLHttpRequest){ 39 | xhr = new XMLHttpRequest(); 40 | }else{ 41 | xhr = new ActiveXObject("Microsoft.XMLHTTP"); 42 | } 43 | ``` 44 | 45 | #### 2、准备请求 46 | 初始化该XMLHttpRequest对象,接受三个参数: 47 | ```javascript 48 | xhr.open(method,url,async); 49 | ``` 50 | 第一个参数表示请求类型的字符串,其值可以是GET或者POST。 51 | GET请求: 52 | ```javascript 53 | xhr.open("GET",demo.php?name=tsrot&age=24,true); 54 | ``` 55 | POST请求: 56 | ```javascript 57 | xhr.open("POST",demo.php,true); 58 | ``` 59 | 第二个参数是要作为请求发送目标的URL。 60 | 第三个参数是true或false,表示请求是以异步还是同步的模式发出。(默认为true,一般不建议为false) 61 | - false:同步模式发出的请求会暂停所有javascript代码的执行,知道服务器获得响应为止,如果浏览器在连接网络时或者在下载文件时出了故障,页面就会一直挂起。 62 | - true:异步模式发出的请求,请求对象收发数据的同时,浏览器可以继续加载页面,执行其他javascript代码 63 | 64 | #### 3、发送请求 65 | ```javascript 66 | xhr.send(); 67 | ``` 68 | 一般情况下,使用Ajax提交的参数多是些简单的字符串,可以直接使用GET方法将要提交的参数写到open方法的url参数中,此时send方法的参数为null或为空。 69 | 70 | GET请求: 71 | ```javascript 72 | xhr.open("GET",demo.php?name=tsrot&age=24,true); 73 | xhr.send(null); 74 | ``` 75 | POST请求: 76 | 如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据: 77 | ```javascript 78 | xhr.open("POST",demo.php,true); 79 | xhr.setRequestHeder("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); 80 | xhr.send("name="+userName+"&age="+userAge); 81 | ``` 82 | 83 | #### 4、处理响应 84 | ```javascript 85 | xhr.onreadystatechange = function(){ 86 | if(xhr.readyState == 4 && xhr.status == 200){ 87 | console.log(xhr.responseText); 88 | } 89 | } 90 | ``` 91 | onreadystatechange 事件: 92 | 当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。 93 | 94 | readyState属性: 95 | 0:已经创建对象,但还没有调用open()方法。 96 | 1:已经调用open()方法,但还没有发送请求。 97 | 2:请求已经发送,标题和状态已经收到,并可用。 98 | 3:接收到来自服务器的响应。 99 | 4:接收完请求数据,表示已经完成请求。 100 | 101 | status属性: 102 | 200:"OK" 103 | 404: 未找到页面 104 | 105 | responseText:获得字符串形式的响应数据 106 | responseXML:获得 XML 形式的响应数据 107 | 返回值一般为json字符串,可以用JSON.parse(xhr.responseText)转化为JSON对象。 108 | 109 | #### 5、完整例子 110 | demo.html 111 | ```javascript 112 | var xhr; 113 | if(XMLHttpRequest){ 114 | xhr = new XMLHttpRequest(); 115 | }else{ 116 | xhr = new ActiveXObject("Microsoft.XMLHTTP"); 117 | }; 118 | 119 | xhr.open("GET","./data.json",true); 120 | xhr.send(); 121 | 122 | xhr.onreadystatechange = function(){ 123 | if(xhr.readyState == 4 && xhr.status == 200){ 124 | console.log(JSON.parse(xhr.responseText).name); 125 | } 126 | } 127 | ``` 128 | data.json 129 | ```json 130 | { 131 | "name":"tsrot", 132 | "age":24 133 | } 134 | ``` 135 | 136 | ### 三、ajax应用场景 137 | 138 | - 场景 1. 数据验证 139 | - 场景 2. 按需取数据 140 | - 场景 3. 自动更新页面 141 | 142 | 143 | ### 四、ajax优缺点 144 | 145 | 优点: 146 | 1、页面无刷新,用户体验好。 147 | 2、异步通信,更加快的响应能力。 148 | 3、减少冗余请求,减轻了服务器负担 149 | 4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。 150 | 151 | 缺点: 152 | 1、ajax干掉了back按钮,即对浏览器后退机制的破坏。 153 | 2、存在一定的安全问题。 154 | 3、对搜索引擎的支持比较弱。 155 | 4、破坏了程序的异常机制。 156 | 5、无法用URL直接访问。 -------------------------------------------------------------------------------- /JS中的call、apply、bind方法详解.md: -------------------------------------------------------------------------------- 1 | # JS中的call、apply、bind方法详解 2 | 3 | @(github.com/tsrot)[call|apply| bind] 4 | 5 | 地址:http://blog.xieliqun.com/2016/08/10/call-apply-bind/ 6 | 7 | > call()、apply()、bind()都是函数对象的一个方法,它们的作用都是改变函数的调用对象。它的使用极大的简化了代码的调用。 8 | 9 | 10 | ---------- 11 | 12 | ### 一、方法定义 13 | 14 | #### call方法 15 | 语法:`call([thisObj[,arg1[, arg2[, [,.argN]]]]])` 16 | 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 17 | 说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 18 | arg1 ... argN为被调用方法的传参。 19 | 20 | #### apply方法 21 | 语法:`apply([thisObj[,argArray]])` 22 | 定义:应用某一对象的一个方法,用另一个对象替换当前对象。 23 | 说明:apply的第一个参数thisObj和call方法的一样,第二个参数argArray为一个传参数组。thisObj如果未传,那么 Global 对象被用作 thisObj。 24 | 25 | #### bind方法 26 | 在ECMAScript5中扩展了叫bind的方法(IE6,7,8不支持) 27 | 语法:`bind([thisObj[,arg1[, arg2[, [,.argN]]]]])` 28 | 定义:应用某一对象的一个方法,用另一个对象替换当前对象。 29 | 说明:bind的thisObj参数也和call方法一样,thisObj如果未传,那么 Global 对象被用作 thisObj。arg1 ... argN可传可不传。如果不传,可以在调用的时候再传。如果传了,调用的时候则可以不传,调用的时候如果你还是传了,则不生效。例如: 30 | ```javascript 31 | var person = { 32 | name:"tsrot", 33 | age:24, 34 | sayHello:function(age){ 35 | console.log(this.name); 36 | console.log(age); 37 | } 38 | }; 39 | var son = { 40 | name:"xieliqun" 41 | }; 42 | var boundFunc = person.sayHello.bind(son); 43 | boundFunc(25); // xieliqun 25 44 | ``` 45 | 46 | ```javascript 47 | var boundFunc = person.sayHello.bind(son,25); 48 | boundFunc(); // xieliqun 25 49 | ``` 50 | 51 | ```javascript 52 | var boundFunc = person.sayHello.bind(son,25); 53 | boundFunc(30); // xieliqun 25 54 | ``` 55 | 56 | ### 二、call、apply、bind的区别 57 | 1、call的arg传参需一个一个传,apply则直接传一个数组。 58 | ```javascript 59 | function hello(name,age){ 60 | console.log(name); 61 | console.log(age); 62 | } 63 | hello.call(this,"tsrot",24); 64 | hello.apply(this,["tsrot",24]); 65 | ``` 66 | 2、call和apply直接执行函数,而bind需要再一次调用。 67 | ```javascript 68 | var obj = { 69 | x: 81, 70 | }; 71 | 72 | var foo = { 73 | getX: function() { 74 | return this.x; 75 | } 76 | } 77 | 78 | console.log(foo.getX.bind(obj)()); //81 79 | console.log(foo.getX.call(obj)); //81 80 | console.log(foo.getX.apply(obj)); //81 81 | ``` 82 | 83 | ### 三、运用场景 84 | 85 | #### 实现继承 86 | ```javascript 87 | function Animal(name) { 88 | this.name = name; 89 | this.showName = function () { 90 | console.log(this.name); 91 | } 92 | } 93 | 94 | function Cat(name) { 95 | Animal.call(this, name); //Cat继承了Animal的showName方法 96 | } 97 | 98 | var cat = new Cat('Black Cat'); 99 | cat.showName(); //Black Cat 100 | ``` 101 | 102 | #### 数组追加 103 | ```javascript 104 | var array1 = [1 , 2 , 3, 5]; 105 | var array2 = ["xie" , "li" , "qun" , "tsrot"]; 106 | Array.prototype.push.apply(array1, array2); 107 | console.log(array1);//[1, 2, 3, 5, "xie", "li", "qun", "tsrot"] 108 | ``` 109 | 110 | #### 获取数组中的最大值和最小值 111 | ```javascript 112 | var num = [1,3,5,7,2,-10,11]; 113 | var maxNum = Math.max.apply(Math, num); 114 | var minNum = Math.min.apply(Math, num); 115 | console.log(maxNum); //11 116 | console.log(minNum); //-10 117 | ``` 118 | 119 | #### 将伪数组转化为数组 120 | ```javascript 121 | var fakeArr = {0:'a',1:'b',length:2}; 122 | var arr1 = Array.prototype.slice.call(fakeArr); 123 | console.log(arr1[0]); //a 124 | var arr2 = [].slice.call(fakeArr); 125 | console.log(arr2[0]); //a 126 | 127 | arr1.push("c"); 128 | console.log(arr1); //["a", "b", "c"] 129 | ``` 130 | 131 | #### 保存this变量 132 | ```javascript 133 | // 正常情况下使用变量保存 this 值 134 | var foo = { 135 | bar : 1, 136 | eventBind: function(){ 137 | var _this = this ; 138 | $('.someClass').on('click',function(event) { 139 | /* Act on the event */ 140 | console.log(_this.bar); //1 141 | }); 142 | } 143 | } 144 | 145 | // 使用 bind 进行函数绑定 146 | var foo = { 147 | bar : 1, 148 | eventBind: function(){ 149 | $('.someClass').on('click',function(event) { 150 | /* Act on the event */ 151 | console.log(this.bar); //1 152 | }.bind(this)); 153 | } 154 | } 155 | ``` -------------------------------------------------------------------------------- /JavaScript中this指向.md: -------------------------------------------------------------------------------- 1 | # JavaScript中this指向 2 | 3 | ------ 4 | 5 | > 对于JavaScript初学者来说,this指针的指向问题一直是很混乱的问题。在不同的场景下,this会化身不同的对象。有一种观点认为,只有正确掌握了 6 | > JavaScript 中的 this 关键字,才算是迈入了 JavaScript 7 | > 这门语言的门槛。在主流的面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象。一般在编译期绑定。而 8 | > JavaScript 中this 在运行期进行绑定的,这是JavaScript 中this 关键字具备多重含义的本质原因。 9 | 10 | 随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,**调用函数的那个对象**。 11 | 12 | 13 | ---------- 14 | 15 | ## 1、 指向window的隐式指向 16 | ```javascript 17 | function sayHello(){ 18 | this.name = "tsrot"; 19 | console.log("hello " + this.name); 20 | } 21 | sayHello() //hello tsrot 22 | ``` 23 | 此时的变量name相当于window.name,因为调用sayHello函数的对象为window,相当于window.sayHello()。和下面两种情况是一样的: 24 | ```javascript 25 | var name = "tsrot"; 26 | function sayHello(){ 27 | console.log("hello " + this.name); 28 | } 29 | sayHello(); //hello tsrot 30 | ``` 31 | 下面的name相当于在window下赋值了两次,谁后面执行就取谁。如果把var name = “xieliqun”放到sayHello()后面,此时输出的就是 hello xieliqun。 32 | ```javascript 33 | var name = "xieliqun"; 34 | function sayHello(){ 35 | this.name = "tsrot"; 36 | } 37 | sayHello(); 38 | console.log("hello " + this.name); //hello tsrot 39 | ``` 40 | *注:当函数在DOM上调用时,未传入this,此时,this也指向window。当传入this时,this指向当前DOM input*,例如下面情况: 41 | ```javascript 42 | 43 | 48 | ``` 49 | ```javascript 50 | 51 | 56 | ``` 57 | 58 | 59 | ---------- 60 | ## 2、 指向当前对象的显式调用 61 | 62 | ### (1)、作为对象方法的调用 63 | 函数还可以作为某个对象的方法调用,这时this就指这个上级对象。 64 | ```javascript 65 | function sayHello(){ 66 | console.log("hello " + this.name); 67 | } 68 | var o = {}; 69 | o.name = "tsrot"; 70 | o.hello = sayHello; 71 | o.hello(); //hello tsrot 72 | ``` 73 | ### (2)、作为构造函数调用 74 | 所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。 75 | ```javascript 76 | function sayHello(){ 77 | this.name = "tsrot"; 78 | } 79 | var o = new sayHello(); 80 | console.log("hello " + o.name); //hello tsrot 81 | ``` 82 | 83 | ---------- 84 | 85 | 86 | ## 3、 指向当前对象的隐式调用 87 | ### (1) call、apply调用 88 | call()、apply()都是函数对象的一个方法,它们的作用是改变函数的调用对象,它们的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。 89 | ```javascript 90 | function sayHello(){ 91 | console.log("hello " + this.name); 92 | } 93 | var o = {}; 94 | o.name = "tsrot"; 95 | o.hello = sayHello; 96 | o.hello.apply(); //hello 97 | ``` 98 | apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。 99 | 如果把最后一行代码修改为 100 | ```javascript 101 | // o.hello.apply(); //hello 102 | o.hello.apply(o); //hello tsrot 103 | o.hello.apply(this); //hello tsrot 104 | o.hello.call(o); //hello tsrot 105 | o.hello.call(this); //hello tsrot 106 | ``` 107 | 此时this就指向对象o了。 108 | ### (2) 原生Function方法bind()调用 109 | 很多人不知道原生js也有bind()方法,一直以为bind()的方法只有jQuery有,我也是最近看别人博客知道的。其实原生的bind和jQuery的bind是不同的,原生的bind相当于apply和call。 110 | ```javascript 111 | var person = { 112 | name:"tsrot", 113 | sayHello:function(){ 114 | console.log("你好,我是"+this.name); 115 | } 116 | } 117 | var boundFunc = person.sayHello.bind(person,person.sayHello); 118 | setTimeout(boundFunc,5000); //5秒后输出 你好,我是tsrot ,[setTimeout 涉及一些执行栈的问题](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout),或者简单的理解,在浏览器中setTimeout是window的属性。 119 | ``` 120 | 下图代码中person.sayHello,相当于在window.person.sayHello,所以this指向window。 121 | ```javascript 122 | var person = { 123 | name:"tsrot", 124 | sayHello:function(){ 125 | console.log("你好,我是"+this.name); 126 | } 127 | } 128 | //var boundFunc = person.sayHello.bind(person,person.sayHello); 129 | setTimeout(person.sayHello,5000); //5秒后输出 你好,我是 130 | ``` 131 | 用apply和call调用时,函数将立即执行 132 | ```javascript 133 | var person = { 134 | name:"tsrot", 135 | sayHello:function(){ 136 | console.log("你好,我是"+this.name); 137 | } 138 | } 139 | var boundFunc = person.sayHello.apply(person,person.sayHello); 140 | setTimeout(boundFunc,5000); //立即输出 你好,我是tsrot 141 | ``` 142 | 143 | 144 | ---------- 145 | ## 4、 当this在构造函数有return时 146 | 如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。 147 | ```javascript 148 | function fn(){ 149 | this.name = "tsrot"; 150 | return {}; 151 | } 152 | var o = new fn(); 153 | console.log(o.name); //undefined 154 | ``` 155 | ```javascript 156 | function fn(){ 157 | this.name = "tsrot"; 158 | return function(){}; 159 | } 160 | var o = new fn(); 161 | console.log(o.name); //undefined 162 | ``` 163 | 当return null和undefined时 164 | ```javascript 165 | function fn(){ 166 | this.name = "tsrot"; 167 | return null; 168 | } 169 | var o = new fn(); 170 | console.log(o.name); //tsrot 171 | ``` 172 | ```javascript 173 | function fn(){ 174 | this.name = "tsrot"; 175 | return undefined; 176 | } 177 | var o = new fn(); 178 | console.log(o.name); //tsrot 179 | ``` 180 | -------------------------------------------------------------------------------- /JavaScript闭包(closure).md: -------------------------------------------------------------------------------- 1 | # JavaScript闭包(closure) 2 | 3 | @(github.com/tsrot)[JavaScript闭包] 4 | 地址:http://blog.xieliqun.com/2016/08/07/javascript-closure/ 5 | 6 | >JavaScript变量分为全局变量和局部变量。Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量,而在函数外部自然无法读取函数内的局部变量。当你需要在函数外调用函数内的局部变量时,此时就要用到一些方法。这个过程就是闭包。 7 | 8 | 9 | ---------- 10 | ###一、JavaScript为什么会有闭包这种东西 11 | JavaScript没有像其它后端语言一样可以直接定义一个变量可供其它外部函数调用的关键字或者方法。于是就产生了闭包这种东西。举个例子: 12 | ```javascript 13 | //内部函数可以访问外部变量 14 | var name = "tsrot"; 15 | function f1(){ 16 | console.log(name); 17 | } 18 | f1(); //tsrot 19 | ``` 20 | ```javascript 21 | //函数外部无法访问函数内部的局部变量 22 | function f2(){ 23 | var name = "tsrot"; //注意:不用var定义的变量,将会默认为全局变量 24 | } 25 | console.log(name); //error undefined 26 | ``` 27 | 如果是java,一个类的私有属性,可以通过公共的方法来获取,比如: 28 | ```java 29 | class Person{ 30 | private String name; 31 | public String getName(){ 32 | return name; 33 | } 34 | } 35 | ``` 36 | ### 二、闭包的概念 37 | 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点: 38 | - 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。 39 | - 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。 40 | 41 | 我的理解就是:让函数外部能调用函数内部变量的一个过程就是闭包。举个例子: 42 | ```javascript 43 | function f1(){ 44 | var name1 = "tsrot"; 45 | function f2(){ 46 | return name1; 47 | } 48 | return f2; 49 | } 50 | var fun = f1(); //此时就访问到了name1的值 51 | console.log(fun()) //tsrot 52 | ``` 53 | 54 | 55 | ###三、闭包的用途 56 | 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。举个例子: 57 | ```javascript 58 | function f1(){ 59 | var n = 0; 60 | function f2(){ 61 | n++; 62 | console.log(n); 63 | } 64 | return f2; //注意此时应该写f2而不是f2() 65 | } 66 | var fun = f1(); 67 | fun(); //1 68 | fun(); //2 此时n就保存在了内存中 69 | ``` 70 | ### 四、闭包的写法 71 | #### 1、原型调用写法 72 | ```javascript 73 | //在函数内部添加属性,然后在外部调用 74 | function Circle(r) { 75 | this.r = r; 76 | } 77 | Circle.PI = 3.14159; 78 | Circle.prototype.area = function() { 79 | return Circle.PI * this.r * this.r; 80 | } 81 | var c = new Circle(1.0); 82 | console.log(c.area()); 83 | ``` 84 | #### 2、函数赋值调用写法 85 | ```javascript 86 | var Circle = function() { 87 | var obj = new Object(); 88 | obj.PI = 3.14159; 89 | obj.area = function(r) { 90 | return this.PI * r * r; 91 | } 92 | return obj; 93 | }; 94 | var c = new Circle(); 95 | console.log(c.area(1.0)); 96 | ``` 97 | #### 3、对象赋值调用写法(常用写法) 98 | ```javascript 99 | var Circle = new Object(); 100 | Circle.PI = 3.14159; 101 | Circle.area = function(r) { 102 | return this.PI * r * r; 103 | }; 104 | consol.log(Circle.area(1.0)); 105 | ``` 106 | #### 4、声明对象调用写法(比较好的一种写法) 107 | ```javascript 108 | var Circle={ 109 | PI : 3.14159, 110 | area : function(r){ 111 | return this.PI * r * r; 112 | } 113 | }; 114 | console.log(Circle.area(1.0)) 115 | ``` 116 | #### 5、Function对象调用写法 117 | ```javascript 118 | //比较少见的一种写法 119 | var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;}"); 120 | var c = new Circle(); 121 | console.log(c.area(1.0)); 122 | ``` 123 | #### 6、匿名函数调用写法(常用写法) 124 | ```javascript 125 | (function(r){ 126 | var PI = 3.14159; 127 | var area = PI * r * r; 128 | console.log(area); 129 | })(1.0) 130 | ``` 131 | #### 7、函数返回值写法(常用写法) 132 | ```javascript 133 | function Circle(r){ 134 | var PI = 3.14159; 135 | function area(){ 136 | return PI * r * r; 137 | } 138 | return area(); 139 | } 140 | console.log(Circle(1.0)); 141 | ``` 142 | ### 五、思考 143 | 思考1:修改下面函数使之输出数组内元素? 144 | ```javascript 145 | function test(){ 146 | var arr = [1,2,3,4,5]; 147 | for(var i=0;i 158 | 159 | 160 | 161 | Document 162 | 163 | 164 |
    165 |
  • 1
  • 166 |
  • 2
  • 167 |
  • 3
  • 168 |
  • 4
  • 169 |
  • 5
  • 170 |
171 | 180 | 181 | 182 | ``` 183 | 答案1 184 | ```javascript 185 | function test(){ 186 | var arr = [1,2,3,4,5] 187 | for(var i=0;i<5;i++){ 188 | (function(i){ 189 | setTimeout(function(){ 190 | console.log(arr[i]); 191 | },1000); 192 | })(i) 193 | } 194 | } 195 | test(); 196 | ``` 197 | 答案2 198 | 199 | ```javascript 200 | 201 | 202 | 203 | 204 | Document 205 | 206 | 207 |
    208 |
  • 1
  • 209 |
  • 2
  • 210 |
  • 3
  • 211 |
  • 4
  • 212 |
  • 5
  • 213 |
214 | 225 | 226 | 227 | ``` -------------------------------------------------------------------------------- /深入了解JavaScript,从作用域链开始(1).md: -------------------------------------------------------------------------------- 1 | # 深入了解JavaScript,从作用域链开始(1) 2 | 3 | 地址:http://blog.xieliqun.com/2016/10/05/scope-chain/ 4 | 5 | > 作用域是每种计算机语言最重要的基础之一,当然它也是JavaScript最重要的概念之一。要想真正的深入了解JavaScript,了解JavaScript的作用域链非常必要。现在让我们深入了解JavaScript作用域和作用域链的工作原理。 6 | 7 | 8 | ---------- 9 | 10 | ### JavaScript的作用域是什么 11 | 12 | 作用域,在维基百科上解释是:在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。 13 | 简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种,局部作用域又称为函数作用域。 14 | 15 | #### 全局作用域 16 | 17 | 在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域: 18 | 19 | ##### (1)程序最外层定义的函数或者变量 20 | ```javascript 21 | var a = "tsrot"; 22 | function hello(){ 23 | alert(a); 24 | } 25 | 26 | function sayHello(){ 27 | hello(); 28 | } 29 | 30 | alert(a); //能访问到tsrot 31 | hello(); //能访问到tsrot 32 | sayHello(); //能访问到hello函数,然后也能访问到tsrot 33 | ``` 34 | 35 | ##### (2)所有末定义直接赋值的变量(不推荐) 36 | ```javascript 37 | function hello(){ 38 | a = "tsrot"; 39 | var b = "hello tsrot"; 40 | } 41 | 42 | alert(a); //能访问到tsrot 43 | alert(b); //error 不能访问 44 | ``` 45 | 46 | ##### (3)所有window对象的属性和方法 47 | 一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。 48 | 49 | 50 | #### 局部作用域(函数作用域) 51 | 52 | 局部作用域在函数内创建,在函数内可访问,函数外不可访问。 53 | ```javascript 54 | function hello(){ 55 | var a = "tsrot"; 56 | alert(a); 57 | } 58 | 59 | hello(); //函数内可访问到tsrot 60 | alert(a); //error not defined 61 | ``` 62 | 63 | ### 作用域链是什么 64 | 65 | 了解作用域链之前我们要知道一下几个概念: 66 | - 变量和函数的声明 67 | - 函数的生命周期 68 | - Activetion Object(AO)、Variable Object(VO) 69 | 70 | 71 | #### 变量和函数的声明 72 | 73 | 在JavaScript引擎解析JavaScript代码的时候,首先,JavaScript引擎会把变量和函数的声明提前进行预解析,然后再去执行其他代码。 74 | 75 | 变量声明:变量的声明只有一种方式,那就是用`var`关键字声明,直接赋值不是一种声明方式。这仅仅是在全局对象上创建了新的属性(而不是变量)。它们有一下区别: 76 | (1)因为它只是一种赋值,所以不会声明提前 77 | ```javascript 78 | alert(a); // undefined 79 | alert(b); // error "b" is not defined 80 | b = 10; 81 | var a = 20; 82 | ``` 83 | (2)直接赋值形式是在执行阶段创建 84 | ```javascript 85 | alert(a); // undefined, 这个大家都知道 86 | b = 10; 87 | alert(b); // 10, 代码执行阶段创建 88 | 89 | var a = 20; 90 | alert(a); // 20, 代码执行阶段修改 91 | ``` 92 | (3)变量不能删除(delete),属性可以删除 93 | ```javascript 94 | a = 10; 95 | alert(window.a); // 10 96 | 97 | alert(delete a); // true 98 | 99 | alert(window.a); // undefined 100 | 101 | var b = 20; 102 | alert(window.b); // 20 103 | 104 | alert(delete b); // false 105 | 106 | alert(window.b); // 仍然为 20,因为变量是不能够删除的。 107 | ``` 108 | 但是,这里有一个意外情况,就是在“eval”的上下文中,变量是可以删除的: 109 | ```javascript 110 | eval('var a = 10;'); 111 | alert(window.a); // 10 112 | 113 | alert(delete a); // true 114 | 115 | alert(window.a); // undefined 116 | ``` 117 | 有些debug工具也是可以删除的,因为它们使用了 eval()方法来执行代码的。 118 | 119 | 函数声明:函数的声明有三种方式 120 | (1)function name( ){ }直接创建方式 121 | ```javascript 122 | function add(a,b){ 123 | return a+b; 124 | } 125 | 126 | add(5,4); 127 | ``` 128 | (2)new Funtion构建函数创建 129 | ```javascript 130 | var add=new Function("a", "b", "return a+b;"); 131 | 132 | add(4,5); 133 | ``` 134 | (3)给变量赋值匿名函数方法创建 135 | ```javascript 136 | var add = function(a,b){ 137 | return a+b; 138 | } 139 | 140 | add(4,5); 141 | ``` 142 | 后面两种方法,在声明前访问时,返回的都是一个undefined的变量。当然,在声明后访问它们都是一个function的函数。 143 | 144 | **注意**:如果变量名和函数名声明时相同,函数优先声明。 145 | ```javascript 146 | alert(x); // function 147 | 148 | var x = 10; 149 | alert(x); // 10 150 | 151 | x = 20; 152 | 153 | function x() {}; 154 | 155 | alert(x); // 20 156 | ``` 157 | 158 | #### 函数的生命周期 159 | 160 | 函数的的生命周期分为创建和执行两个阶段。 161 | 162 | 在函数创建阶段,JS解析引擎进行预解析,会将函数声明提前,同时将该函数放到全局作用域中或当前函数的上一级函数的局部作用域中。 163 | 164 | 在函数执行阶段,JS引擎会将当前函数的局部变量和内部函数进行声明提前,然后再执行业务代码,当函数执行完退出时,释放该函数的执行上下文,并注销该函数的局部变量。 165 | 166 | #### 什么是AO、VO 167 | 168 | 英文解释: 169 | AO:Activetion Object(活动对象) 170 | VO:Variable Object(变量对象) 171 | 172 | VO对应的是函数创建阶段,JS解析引擎进行预解析时,所有的变量和函数的声明,统称为Variable Object。该变量与执行上下文相关,知道自己的数据存储在哪里,并且知道如何访问。VO是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容: 173 | - 变量 (var, 变量声明); 174 | - 函数声明 (FunctionDeclaration, 缩写为FD); 175 | - 函数的形参 176 | 177 | 举个例子: 178 | ```javascript 179 | function add(a,b){ 180 | var sum = a + b; 181 | function say(){ 182 | alert(sum); 183 | } 184 | return sum; 185 | } 186 | // sum,say,a,b 组合的对象就是VO,不过该对象的值基本上都是undefined 187 | ``` 188 | 189 | 190 | AO对应的是函数执行阶段,当函数被调用执行时,会建立一个执行上下文,该执行上下文包含了函数所需的所有变量,该变量共同组成了一个新的对象就是Activetion Object。该对象包含了: 191 | - 函数的所有局部变量 192 | - 函数的所有命名参数 193 | - 函数的参数集合 194 | - 函数的this指向 195 | 196 | 举个例子: 197 | ```javascript 198 | function add(a,b){ 199 | var sum = a + b; 200 | function say(){ 201 | alert(sum); 202 | } 203 | return sum; 204 | } 205 | 206 | add(4,5); 207 | // 我用JS对象来表示AO 208 | // AO = { 209 | // this : window, 210 | // arguments : [4,5], 211 | // a : 4, 212 | // b : 5, 213 | // say : , 214 | // sum : undefined 215 | // } 216 | ``` 217 | 218 | #### JavaScript作用域链 219 | 220 | 现在我们回到主题,作用域链。 221 | 222 | 当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)来保证对执行环境有权访问的变量和函数的有序访问。作用域第一个对象始终是当前执行代码所在环境的变量对象(VO)。 223 | ```javascript 224 | function add(a,b){ 225 | var sum = a + b; 226 | return sum; 227 | } 228 | ``` 229 | 假设函数是在全局作用域中创建的,在函数a创建的时候,它的作用域链填入全局对象,全局对象中有所有全局变量,此时的全局变量就是VO。此时的作用域链就是: 230 | 231 | ```flow 232 | 此时作用域链(Scope Chain)只有一级,就为Global Object 233 | 234 | scope(add) -> Global Object(VO) 235 | 236 | VO = { 237 | this : window, 238 | add : 239 | } 240 | ``` 241 | 242 | 如果是函数执行阶段,那么将其activation object(AO)作为作用域链第一个对象,第二个对象是上级函数的执行上下文AO,下一个对象依次类推。 243 | ```javascript 244 | add(4,5); 245 | ``` 246 | 例如,调用add后的作用域链是: 247 | 248 | ```flow 249 | 此时作用域链(Scope Chain)有两级,第一级为AO,然后Global Object(VO) 250 | 251 | scope(add) -> AO -> VO 252 | 253 | AO = { 254 | this : window, 255 | arguments : [4,5], 256 | a : 4, 257 | b : 5, 258 | sum : undefined 259 | } 260 | 261 | VO = { 262 | this : window, 263 | add : 264 | } 265 | ``` 266 | 在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。 267 | 268 | 看过上面的内容后,可能还有人不懂,我再通熟易懂的解释一遍,先举个例子: 269 | ```javascript 270 | var x = 10; 271 | 272 | function foo() { 273 | var y = 20; 274 | 275 | function bar() { 276 | var z = 30; 277 | 278 | console.log(x + y + z); 279 | }; 280 | 281 | bar() 282 | }; 283 | 284 | foo(); 285 | ``` 286 | 上面代码的输出结果为”60″,函数bar可以直接访问”z”,然后通过作用域链访问上层的”x”和”y”。此时的作用域链为: 287 | ```flow 288 | 此时作用域链(Scope Chain)有三级,第一级为bar AO,第二级为foo AO,然后Global Object(VO) 289 | 290 | scope -> bar.AO -> foo.AO -> Global Object 291 | 292 | bar.AO = { 293 | z : 30, 294 | __parent__ : foo.AO 295 | } 296 | 297 | foo.AO = { 298 | y : 20, 299 | bar : , 300 | __parent__ : 301 | } 302 | 303 | Global Object = { 304 | x : 10, 305 | foo : , 306 | __parent__ : null 307 | } 308 | ``` 309 | 310 | 未完待续。。。 -------------------------------------------------------------------------------- /JS的原型和原型链.md: -------------------------------------------------------------------------------- 1 | # JS的原型和原型链 2 | 3 | @(github.com/tsrot)[原型|原型链] 4 | 5 | 地址:http://blog.xieliqun.com/2016/08/20/prototype/ 6 | 7 | > 在JavaScript的使用过程中,我们经常会遇到prototype,可能了解一点,它是一个对象的原型,用来做原型继承的。这样去理解就有点不准确了,今天就让我们深入的去了解它。 8 | 9 | 10 | ---------- 11 | 12 | ### 了解一些概念 13 | 14 | 在读这篇文章之前,你应该去在自己的脑海问几个问题: 15 | 1、什么是原型? 16 | 2、什么事原型链? 17 | 3、prototype与\__proto__有什么不同,有什么联系? 18 | 4、constructor与面两个有什么联系,怎么用? 19 | 20 | 如果你把上面这四个问题都解决了,那你就真正了解了JS的原型和原型链。接下来,咱们一个一个问题去解决。 21 | 22 | 23 | ### 什么是原型 24 | 25 | JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。每个对象都有原型(null和undefined除外),你可以把它理解为对象的默认属性和方法。 26 | 27 | 你可以把下面的代码在浏览器打印出来看一下。 28 | 29 | ```javascript 30 | console.log(Object.prototype); //Object{} 31 | 32 | var o = new Object(); 33 | console.log(o.prototype); //undefined 34 | 35 | console.log(Array.prototype); //[Symbol(Symbol.unscopables): Object] 36 | 37 | console.log(Function.prototype); //function(){} 38 | 39 | function hello(){ 40 | console.log("hello"); 41 | } 42 | hello.prototype = "hello world"; 43 | console.log(hello.prototype); //hello world 44 | ``` 45 | 46 | **Object**:Object是一个函数对象,Object的原型就是一个Object对象,它里面存在着一些对象的方法和属性,例如最常见的toString方法。 47 | 48 | **新建对象**:用new Object或者{}建的对象是普通对象,它没有prototype属性,只有\__proto__属性,它指向Object.prototype。 49 | 50 | **Array**:Array也是一个函数对象,它的原型就是Array.prototype,它里面存在着一些数组的方法和属性,例如常见的push,pop等方法。 51 | 52 | **Function**:Function也是一个函数对象,但它有点特殊,它的原型就是一个function空函数。 53 | 54 | **自定义函数**:它的原型就是你给它指定的那个东西。如果你不指定,那它的原型就是一个Object.prototype。 55 | 56 | 57 | 58 | ### 什么是原型链 59 | 60 | 在 javaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。 61 | 62 | JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。 63 | 64 | ```javascript 65 | var o = { 66 | a:1, 67 | b:2 68 | }; 69 | console.log(o.toString()); //不报错,o上没有toString方法,但是Object上有 70 | 71 | console.log(o.push("c")); //报错,o上没有这个方法,Object上也没有这个方法。 72 | 73 | console.log(o.a); //1 74 | console.log(o.c); //undefined 75 | ``` 76 | 当你用new Object或者直接定义一个对象时,它的原型链就是: 77 | o ==》 Object.prototype ==》 null 78 | 但你访问o上没有的属性或方法时,JS会往Object.prototype上寻找该属性和方法。如果有则直接返回,如果没有,方法则报错,这个方法未定义,属性则返回undefined。 79 | 80 | ```javascript 81 | function Person(name){ 82 | this.name = name; 83 | } 84 | Person.prototype = {age:24}; 85 | 86 | var tsrot = new Person("tsrot"); 87 | 88 | console.log(tsrot.name); //tsrot 89 | console.log(tsrot.age); //24 90 | console.log(tsrot.toString()); //[object Object] 91 | ``` 92 | 当你用构造函数(构造函数我们一般首字母大写)建立一个对象时,它的原型链就是: 93 | tsrot ==》 Person.prototype ==》 Object.prototype ==》 null 94 | 如果没有定义Person.prototype这一环,则直接跳到下一环。 95 | 96 | 97 | 来点更复杂的。 98 | ```javascript 99 | function Parent(){ 100 | this.name = "i am parent"; 101 | } 102 | Parent.prototype = {age:24}; 103 | 104 | function Child(){ 105 | this.name = "i am child"; 106 | } 107 | 108 | Child.prototype = Object.create(Parent.prototype); //让Child的原型指向Parent的原型 109 | Child.prototype.constructor = Child; //把child的构造函数指向回来,否则它将指向Parent。虽然在这没什么影响,但要养成代码的严谨性 110 | 111 | var child = new Child(); 112 | 113 | console.log(child.name); //i am child 114 | console.log(child.age); //24 115 | console.log(child.toString()); //[object Object] 116 | ``` 117 | 当你需要父类的属性和方法时,你可以把它的原型指向父类的原型。此时的原型链就是: 118 | child ==》 Parent.prototype ==》 Object.prototype ==》 null 119 | 120 | ```javascript 121 | var arr = [1,2,3]; 122 | 123 | console.log(arr); //[1,2,3] 124 | arr.push(4); 125 | console.log(arr); //[1,2,3,4] 126 | ``` 127 | 数组也是一个对象,不过它是由Array构造函数new而来的,所以它的原型链就是: 128 | arr ==》 Array.prototype ==》 Object.prototype ==》 null 129 | 130 | 131 | ```javascript 132 | var fun = function(){ 133 | var hello = "i am function"; 134 | } 135 | 136 | console.log(fun.name); //fun 137 | ``` 138 | fun是一个函数对象,它是由Function构造函数new而来的,所以它的原型链就是: 139 | fun ==》 Function.prototype ==》 Object.prototype ==》 null 140 | fun它没有name属性,但是Function它有,所以这个name就是Function原型上的。 141 | 142 | 143 | 144 | ### prototype与\__proto__ 145 | 146 | 在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个\__proto\__属性指向这个原型,而函数的原型是一个对象(函数点prototype也是一个普通对象,Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性),所以这个对象也会有一个\__proto\__指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。普通对象没有prototype,但有\__proto\__属性。 147 | 148 | ```javascript 149 | function f1(){}; 150 | 151 | console.log(f1.prototype) //Object{} 152 | 153 | console.log(typeof f1.prototype) //Object 154 | 155 | console.log(typeof Function.prototype) // Function,这个特殊 156 | 157 | console.log(typeof Object.prototype) //Object 158 | 159 | console.log(typeof Function.prototype.prototype) //undefined 160 | ``` 161 | 162 | JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做\__proto\__的内置属性,用于指向创建它的函数对象的原型对象prototype。 163 | 164 | **普通对象的\__proto\__** 165 | ```javascript 166 | var o = {name:"tsrot"}; 167 | 168 | console.log(o.__proto__); //Object{} 169 | console.log(o.prototype); //undefined 170 | console.log(o.__proto__ === Object.prototype); //true 171 | 172 | ``` 173 | 174 | **构造对象的\__proto\__** 175 | ```javascript 176 | function Parent(){ 177 | this.name = "i am parent"; 178 | } 179 | Parent.prototype = {age:24}; 180 | 181 | function Child(){ 182 | this.name = "i am child"; 183 | } 184 | 185 | Child.prototype = Object.create(Parent.prototype); 186 | Child.prototype.constructor = Child; 187 | 188 | var child = new Child(); 189 | 190 | console.log(child.__proto__); //Object{} 191 | 192 | console.log(Child.prototype); //Object{} 193 | 194 | console.log(child.__proto__ === Child.prototype); //true 195 | 196 | console.log(Parent.prototype.__proto__ === Object.prototype); //true 197 | 198 | ``` 199 | 200 | **数组的\__proto\__** 201 | ```javascript 202 | var arr = [1,2,3]; 203 | 204 | console.log(arr.__proto__); //[Symbol(Symbol.unscopables): Object] 205 | 206 | console.log(Array.prototype); //[Symbol(Symbol.unscopables): Object] 207 | 208 | console.log(arr.__proto__ === Array.prototype); //true 209 | 210 | ``` 211 | 212 | **函数的\__proto\__** 213 | ```javascript 214 | var fun = function(){ 215 | var hello = "i am function" 216 | } 217 | 218 | fun.prototype = {name:"tsrot"}; 219 | 220 | console.log(fun.prototype); //Object {name: "tsrot"} 221 | 222 | console.log(fun.__proto__); //function(){} 223 | 224 | console.log(fun.prototype === fun.__proto__); //false 225 | 226 | console.log(fun.__proto__ === Function.prototype); //true 227 | ``` 228 | 229 | 230 | ### constructor属性 231 | 232 | 原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用: 233 | 234 | ```javascript 235 | function Person(name){ 236 | this.name = name; 237 | } 238 | 239 | console.log(Person.prototype.constructor === Person); //true 240 | 241 | console.log(Function.prototype.constructor === Function); //true 242 | 243 | console.log(Object.prototype.constructor === Object); //true 244 | ``` 245 | 246 | 用构造函数创建的对象,它的constructor属性就是它的构造函数。 247 | ```javascript 248 | function Person(name){ 249 | this.name = name; 250 | } 251 | 252 | var person = new Person(); 253 | 254 | console.log(person.constructor === Person); //true 255 | 256 | ``` 257 | 258 | ### 参考文章 259 | 1、[JavaScript Prototype Chains](https://www.toptal.com/javascript/javascript-prototypes-scopes-and-performance-what-you-need-to-know) 260 | 2、[Understanding JavaScript Prototypes](https://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/) 261 | 3、[继承与原型链](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) -------------------------------------------------------------------------------- /React学习资源汇总.md: -------------------------------------------------------------------------------- 1 | # React学习资源汇总 2 | 3 | 博客地址:http://blog.xieliqun.com/2016/11/05/react-study/ 4 | 5 | 6 | > React是如今最热门的前端框架,它设计思路独特,性能卓越,逻辑简单,受到了广泛开发者的喜爱。一旦接触她,你就会被她深深吸引。 7 | > 我断断续续的学了将近两个月,今天终于有时间把自己学习React的一些学习资料总结一下。 8 | 9 | **React 官方** 10 | - 官网地址:http://facebook.github.io/react/ 11 | - Github地址:https://github.com/facebook/react 12 | 13 | ## 设计思想 14 | 15 | 学习React之前,我们先了解一下它的设计思想,它与如今其他热门的前端框架有什么不同?它能为我们的开发解决哪些痛点? 16 | 17 | 1. [React 设计思想](https://github.com/react-guide/react-basic) 18 | 2. [React的设计哲学 - 简单之美](http://www.infoq.com/cn/articles/react-art-of-simplity/) 19 | 3. [颠覆式前端UI开发框架:React](http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react/) 20 | 21 | ## 初学者入门 22 | 23 | ### 文章 24 | 25 | 可以结合一些简单demo去看文章,例如你在看阮一峰的React 入门实例教程时,可结合他写的入门demo,或官方给的demo。当然你也要边学习边自己去写一些简单demo,去改改别人写的一些React 项目。一定要多动手。 26 | 27 | 1. [React 入门实例教程-阮一峰](http://www.ruanyifeng.com/blog/2015/03/react.html):建议先看demo 28 | 2. [一看就懂的ReactJs入门教程(精华版)](http://www.cocoachina.com/webapp/20150721/12692.html) 29 | 3. [React 教程-菜鸟教程](http://www.runoob.com/react/react-tutorial.html):安装那节好像有点错 30 | 4. [React 入门,5个常用DEMO展示](http://blog.csdn.net/iambinger/article/details/51803606) 31 | 5. [如何学习React](http://www.360doc.com/content/16/0129/07/13518188_531384175.shtml) 32 | 6. [给新手的 React&Webpack 上手教程](https://github.com/theJian/build-a-hn-front-page) 33 | 7. [ReactJS 傻瓜教程](https://zhuanlan.zhihu.com/p/19896745?columnSlug=FrontendMagazine) 34 | 8. [React 最简单的入门应用项目](http://guodavid.tk/2016/08/29/React-Message-board/) 35 | 36 | ### 入门 demo 37 | 38 | 1. [官方入门 demo](https://github.com/facebook/react/tree/master/examples):可结合官方的入门文档 39 | 2. [入门 demo-阮一峰](https://github.com/ruanyf/react-demos):结合入门文章 40 | 3. [模仿知乎界面的一个简单React demo](https://github.com/tsrot/react-zhihu):结合 [ReactJS中文基础视频教程-爱酷](http://www.icoolxue.com/album/show/262) 41 | 42 | ### 入门视频教程 43 | 44 | 一定要边看边写,不要囫囵吞枣的看一遍就好了。 45 | 46 | 1. [React入门-慕课网](http://www.imooc.com/learn/504) 47 | 2. [ReactJS中文基础视频教程-爱酷](http://www.icoolxue.com/album/show/262) 48 | 3. [ReactJS中文视频教程](http://react-china.org/t/reactjs/584) 49 | 4. [React教程- 汇智网](http://www.hubwiz.com/course/552762019964049d1872fc88/?ch=alloyteam) 50 | 51 | ### 入门实战视频 52 | 53 | 了解React开发流程,作者的编码思路,写作规范。 54 | 55 | 1. [React实战--打造画廊应用(上)](http://www.imooc.com/learn/507) 56 | 2. [React实战--打造画廊应用(下)](http://www.imooc.com/learn/652) 57 | 3. [ReactJS中文基础视频教程](http://zexeo.com/course/56753a22b2b8de861c0d281a) 58 | 4. [构建实时聊天应用](http://zexeo.com/course/5672c2bd52b470c02bc28b6c) 59 | 60 | ## 开发文档 61 | 62 | 开发其实不用详细去全看,在你做项目时,遇到不懂的就去查看一下文档,我认为这样效率更高一点。当然你有时间也可以一步步去阅读。 63 | 64 | 1. [官方文档](https://facebook.github.io/react/docs/hello-world.html) 65 | 2. [中文文档](http://reactjs.cn/react/docs/getting-started-zh-CN.html) 66 | 67 | ## 学习网站 68 | 69 | 在学习中我们会遇到 一些问题,可以去社区或一些网站寻找答案,下面推荐一些好的React 社区和学习网站。 70 | 71 | 1. [React中文社区](http://react-china.org/) 72 | 2. [React 中文索引](http://nav.react-china.org/) 73 | 2. [React知识库](http://lib.csdn.net/base/react) 74 | 3. [A quick start to React](https://codepicnic.com/posts/a-quick-start-to-react-0777d5c17d4066b82ab86dff8a46af6f) 75 | 4. [stack overflow](http://stackoverflow.com/questions/tagged/reactjs) 76 | 5. [知乎 React 话题](https://www.zhihu.com/topic/20013159/hot) 77 | 6. [segmentfault React 话题](https://segmentfault.com/t/react.js) 78 | 79 | ## React技术栈 80 | 81 | React是一款非常优秀的前端框架,你要发挥它完全的性能,你就要结合其他一些技术,例如webpack、redux、react-router等。 82 | 83 | 1. [React 技术栈系列教程](http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html) 84 | 2. [百度母婴技术团队—基于Reactjs实现webapp](https://github.com/my-fe/wiki/issues/1) 85 | 3. [Building a React Universal Blog App](https://www.sitepoint.com/building-a-react-universal-blog-app-a-step-by-step-guide/) 86 | 4. [React为啥非得使用immutable.js](http://react-china.org/t/react-immutable-js/3770) 87 | 5. [React Server Side Rendering 解决 SPA 应用的 SEO 问题](https://blog.coding.net/blog/React-Server-Side-Rendering-for-SPA-SEO) 88 | 89 | 6. [webpack官方文档](http://webpack.github.io/docs/) 90 | 7. [Webpack 中文指南](http://webpackdoc.com/) 91 | 8. [webpack一小时快速入门](http://www.w2bc.com/Article/50764) 92 | 9. [使用webpack轻松构建你的第一个react开发框架](http://www.jianshu.com/p/c8a805145046) 93 | 10. [入门Webpack,看这篇就够了](http://www.jianshu.com/p/42e11515c10f#):写的很不错,逐级深入,适合入门,有点长,耐心看完 94 | 95 | 10. [react-router](https://github.com/ReactTraining/react-router) 96 | 11. [React Router 中文文档](https://react-guide.github.io/react-router-cn/) 97 | 12. [React Router 官方 demo](https://github.com/reactjs/react-router-tutorial/tree/master/lessons) 98 | 99 | 13. [Redux官网](http://redux.js.org/) 100 | 14. [Redux 中文文档](http://cn.redux.js.org/index.html) 101 | 15. [Redux 官方 demo](https://github.com/reactjs/redux/tree/master/examples) 102 | 16. [Redux 莞式教程](https://github.com/kenberkeley/redux-simple-tutorial) 103 | 17. [Redux 视频教程](https://egghead.io/courses/getting-started-with-redux) 104 | 18. [redux 大法好](http://qiutc.me/post/redux-%E5%A4%A7%E6%B3%95%E5%A5%BD-%E2%80%94%E2%80%94-%E5%85%A5%E9%97%A8%E5%AE%9E%E4%BE%8B-TodoList.html) 105 | 19. [Flux 傻瓜教程](https://zhuanlan.zhihu.com/p/19900243?columnSlug=FrontendMagazine) 106 | 20. [react+redux渲染性能优化原理](http://foio.github.io/react-redux-performance-boost/) 107 | 21. [React开发社区](https://react.ctolib.com/) 108 | 22. [数据流管理架构之 Redux 介绍](http://www.alloyteam.com/2015/09/react-redux/) 109 | 23. [React同构直出优化总结](http://www.alloyteam.com/2016/06/react-isomorphic/) 110 | 24. [前端路由实现与 react-router 源码分析](http://www.alloyteam.com/2016/05/router/) 111 | 25. [如何开发一个 Webpack Loader ( 一 )](http://www.alloyteam.com/2016/01/webpack-loader-1/) 112 | 26. [服务器端渲染实践小结](http://www.alloyteam.com/2015/10/8783/) 113 | 27. [听说你需要这样了解 Redux](https://github.com/rccoder/blog/issues/18) 114 | 28. [学习Redux刷新了我的前端App状态管理观](http://www.jianshu.com/p/94d8f8a36ab0) 115 | 29. [Learn React & Webpack by building a hacker news front page](https://github.com/theJian/build-a-hn-front-page) 116 | 117 | ## 开发工具 118 | 119 | - [react-devtools](https://github.com/facebook/react-devtools) 120 | - [React DevTools 正式发布,完全支持 React Native](http://www.oschina.net/news/65837/react-devtools-2-0) 121 | - [redux-devtools](https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md) 122 | - [Redux超酷的开发工具Redux-Devtools](http://www.zhufengpeixun.cn/article/151) 123 | 124 | ## redux 常用中间件或工具 125 | 126 | - [redux-thunk](https://github.com/gaearon/redux-thunk) 127 | - [redux-gen](https://github.com/weo-edu/redux-gen) 128 | - [redux-undo](https://github.com/omnidan/redux-undo) 129 | - [react-router-redux](https://github.com/reactjs/react-router-redux) 130 | - [react-redux-form](https://github.com/davidkpiano/react-redux-form) 131 | 132 | 133 | ## React 开源项目 134 | 135 | 介绍一些国内外比较好的 React 开源项目。 136 | 137 | 国内: 138 | - [阿里的 React 组件库](https://github.com/react-component) 139 | - [Ant Design](https://github.com/ant-design/ant-design) 140 | - [简易留言板](https://github.com/tsrot/react-demo) 141 | - [react-zhihu](https://github.com/tsrot/react-zhihu) 142 | - [React的扫雷游戏](https://github.com/cjohansen/react-sweeper) 143 | - [在线聊天室](https://github.com/redsx/CR) 144 | - [使用React技术栈开发SPA](https://github.com/JasonBai007/reactSPA) 145 | - [阔论留言评论](https://github.com/NumerHero/kuolun) 146 | - [React版cnode社区](https://github.com/lzxb/react-cnode) 147 | - [适合新手学习的Demo, React + react-router + webpack + babel + Node + express + mongodb](https://github.com/rongchanghai/justForYou) 148 | 149 | 国外: 150 | - [Relax](https://github.com/relax/relax) 151 | - [SoundRedux](https://github.com/andrewngu/sound-redux/) 152 | - [Gatsby](https://github.com/gatsbyjs/gatsby) 153 | - [isomorphic500](https://github.com/gpbl/isomorphic500) 154 | - [NuclearMail](https://github.com/ianobermiller/nuclearmail) 155 | - [Picard](https://github.com/Automattic/Picard) 156 | - [React Color](https://github.com/casesandberg/react-color) 157 | - [Sentry](https://github.com/getsentry/sentry/) 158 | - [react-hn](https://github.com/insin/react-hn) 159 | - [Perseus](https://github.com/khan/perseus) 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /事件绑定、事件监听、事件委托.md: -------------------------------------------------------------------------------- 1 | # 事件绑定、事件监听、事件委托 2 | @(github.com/tsrot)[事件绑定|事件监听|事件委托] 3 | 4 | 地址:http://blog.xieliqun.com/2016/08/12/event-delegate/ 5 | 6 | > 在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定、事件监听、事件委托(事件代理)等。这些名词是什么意思呢,有什么作用呢? 7 | 8 | 9 | ---------- 10 | 11 | ### 事件绑定 12 | 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称。 13 | 14 | 在JavaScript中,有三种常用的绑定事件的方法: 15 | - 在DOM元素中直接绑定; 16 | - 在JavaScript代码中绑定; 17 | - 绑定事件监听函数。 18 | 19 | #### 在DOM中直接绑定事件 20 | 我们可以在DOM元素上绑定onclick、onmouseover、onmouseout、onmousedown、onmouseup、ondblclick、onkeydown、onkeypress、onkeyup等。好多不一一列出了。如果想知道更多事件类型请查看,[DOM事件](http://www.runoob.com/jsref/dom-obj-event.html)。 21 | 22 | ```javascript 23 | 24 | 25 | 30 | ``` 31 | 32 | #### 在JavaScript代码中绑定事件 33 | 34 | 在JavaScript代码中(即`script`标签内)绑定事件可以使JavaScript代码与HTML标签分离,文档结构清晰,便于管理和开发。 35 | 36 | ```javascript 37 | 38 | 39 | 44 | ``` 45 | 46 | #### 使用事件监听绑定事件 47 | 绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。下面详细介绍,事件监听。 48 | 49 | ### 事件监听 50 | 关于事件监听,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。 51 | 52 | 起初Netscape制定了JavaScript的一套事件驱动机制(即事件捕获)。随即IE也推出了自己的一套事件驱动机制(即事件冒泡)。最后W3C规范了两种事件机制,分为捕获阶段、目标阶段、冒泡阶段。IE8以前IE一直坚持自己的事件机制(前端人员一直头痛的兼容性问题),IE9以后IE也支持了W3C规范。 53 | 54 | #### W3C规范 55 | 56 | 语法: 57 | ```javascript 58 | element.addEventListener(event, function, useCapture) 59 | ``` 60 | 61 | event : (必需)事件名,支持所有[DOM事件](http://www.runoob.com/jsref/dom-obj-event.html)。 62 | function:(必需)指定要事件触发时执行的函数。 63 | useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。 64 | 65 | 注:IE8以下不支持。 66 | ```javascript 67 | 68 | 69 | 75 | ``` 76 | 77 | #### IE标准 78 | 79 | 语法: 80 | ```javascript 81 | element.attachEvent(event, function) 82 | ``` 83 | event:(必需)事件类型。需加“on“,例如:onclick。 84 | function:(必需)指定要事件触发时执行的函数。 85 | 86 | ```javascript 87 | 88 | 89 | 95 | ``` 96 | 97 | #### 事件监听的优点 98 | 99 | 1、可以绑定多个事件。 100 | ```javascript 101 | 102 | 103 | 112 | ``` 113 | 常规的事件绑定只执行最后绑定的事件。 114 | 115 | ```javascript 116 | 117 | 118 | 130 | ``` 131 | 两个事件都执行了。 132 | 133 | 2、可以解除相应的绑定 134 | ```javascript 135 | 136 | 137 | 150 | ``` 151 | 152 | #### 封装事件监听 153 | ```javascript 154 | 155 | 156 | //绑定监听事件 157 | function addEventHandler(target,type,fn){ 158 | if(target.addEventListener){ 159 | target.addEventListener(type,fn); 160 | }else{ 161 | target.attachEvent("on"+type,fn); 162 | } 163 | } 164 | 165 | //移除监听事件 166 | function removeEventHandler(target,type,fn){ 167 | if(target.removeEventListener){ 168 | target.removeEventListener(type,fn); 169 | }else{ 170 | target.detachEvent("on"+type,fn); 171 | } 172 | } 173 | 174 | //测试 175 | var btn5 = document.getElementById("btn5"); 176 | addEventHandler(btn5,"click",hello1);//添加事件hello1 177 | addEventHandler(btn5,"click",hello2);//添加事件hello2 178 | removeEventHandler(btn5,"click",hello1);//移除事件hello1 179 | ``` 180 | 181 | ### 事件委托 182 | 183 | 事件委托就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。 184 | 185 | ```javascript 186 | 187 | 188 | var btn6 = document.getElementById("btn6"); 189 | document.onclick = function(event){ 190 | event = event || window.event; 191 | var target = event.target || event.srcElement; 192 | if(target == btn6){ 193 | alert(btn5.value); 194 | } 195 | } 196 | ``` 197 | 上面只是个例子,代码尽可能的简化了。在实际的代码中 我们可能用到jQuery的live()、delegate()、bind()、on()等。 198 | 199 | #### 事件委托优点 200 | 201 | 1、提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。[实例分析JavaScript中的事件委托和事件绑定](http://www.diguage.com/archives/71.html),这篇文章写得还不错。 202 | 203 | **传统写法** 204 | 205 | ```javascript 206 |
    207 |
  • item1
  • 208 |
  • item2
  • 209 |
  • item3
  • 210 |
211 | 212 | 227 | ``` 228 | 229 | **事件委托** 230 | ```javascript 231 |
    232 |
  • item1
  • 233 |
  • item2
  • 234 |
  • item3
  • 235 |
236 | 237 | 253 | ``` 254 | 255 | 2、动态的添加DOM元素,不需要因为元素的改动而修改事件绑定。 256 | 257 | **传统写法** 258 | ```javascript 259 |
    260 |
  • item1
  • 261 |
  • item2
  • 262 |
  • item3
  • 263 |
264 | 265 | 283 | 284 | ``` 285 | 点击item1到item3都有事件响应,但是点击item4时,没有事件响应。说明传统的事件绑定无法对动态添加的元素而动态的添加事件。 286 | 287 | **事件委托** 288 | ```javascript 289 |
    290 |
  • item1
  • 291 |
  • item2
  • 292 |
  • item3
  • 293 |
294 | 295 | 311 | 312 | ``` 313 | 当点击item4时,item4有事件响应。说明事件委托可以为新添加的DOM元素动态的添加事件。 --------------------------------------------------------------------------------