JavaScript 三座大山
来源:互联网 发布:java使用md5加密解密 编辑:程序博客网 时间:2024/05/16 14:58
原型与原型链及this
声明:下面说的对象是指 object Array Function 除 null 以外
1 任何对象 都可以做自由添加属性
var obj = {a:10, b:1}obj.qq = "123456";//Object {a: 10, b: 1, qq: "123456"}
2 在JavaScript中任何对象都会有__proto__ 属性 (隐式原型)
3 在JavaScript中函数对象 都会有prototype属性 (显式原型)
4 任意对象的__proto__ (隐式原型)指向 其构造函数的prototype(显式原型)
//安装规范 构造函数名 采用大驼峰命名方式 var Foo = function () { this.name = "long"; this.age = "10";}var foo = new Foo();foo.__proto__ === Foo.prototype//true
5 任何一个函数调用其属性时,如果自己没有对应的属性就回去父类上找,通过原型链一步步向上查找,直至null
var Foo = function () { this.name = "long"; this.age = "10";}Foo.afert = function () {console.log(1);}var foo = new Foo();foo.__proto__ === Foo.prototype//trueFoo.__proto__ === Function.prototype//truefoo.toString();//有toString方法,因为Function 有。foo.name;//用为其父类有//"long"foo.prototype//undefinedfoo.prototype = {ele: "element", clazz: "class"}//Object {ele: "element", clazz: "class"}foo.prototype.clazz//"class"foo.prototype.hasOwnProperty("toString")//falsefoo.prototype.hasOwnProperty("ele") //可以通过hasOwnProperty方法判断某个属性是对象自己的还重父类继承过来的//truefoo.name//"long"foo.age//"10"foo.afert//undefined//prototype (显式原型上的属性是可以被 子类继承的)//Foo.xxx xxx属性是不会被继承的
========== this 指向问题先要搞清js的 “定义”与“执行”============
this 要在执行时才能确定值,定义时无法确认("谁调指谁,没有谁调用时指window")eg:var a = { name: "long", fn: function () { console.log(this.name);//就是这里有bug 在定义时也无法确定 }}a.fn();// this === aa.fn.call({name: "gong"})// this === {name: "gong"}var fn1 = a.fn;fn1(); // this === window//this 的指向作为构造函数执行 this.name .....作为对象属性执行 f.callname()作为普通函数执行 username() this 指windowcall apply bind 可以改变this的执行 call(面量对象) apply(数组)eg://执行构造函数function Foo (name) { //this = {}; this.name = name; //return this;}var f = new Foo('long');f.name;//执行对象属性var obj = { name: 'long', sex: 'man', say: function() { console.log(this.name); }}obj.say();// this === obj//作为普通函数执行function testfn () { console.log(this);//this === window}testfn();//call apply bind/*全局中:在执行前会确认一遍, 变量定义 函数声明.函数中:在执行前会确认一遍,变量定义 函数声明 this argument*/function fn1 (name) { console.log(name); console.log(this); console.log(arguments);}fn1.call({x:100}, 'long', '25');// this === {x:100}fn1();function fn11 (name) { console.log(name); console.log(this); console.log(arguments);};fn11.apply({x:100}, ['long', '25']);// this === {x:100}fn11();function fn2 (name) { console.log(name); console.log(this);}fn2("long");// this === windowfunction fn3 (name) { console.log(name); console.log(this);}.bind({y: 200});// bind 就是用来改变this指向的fn3("long");//【.bind 必须是函数表达式 如果是函数表达式会报错】var fn4 = function (name) { console.log(name); console.log(this);}.bind({y: 200});// bind 就是用来改变this指向的fn4("long");// this === {y: 200}//分清 函数定义 和 函数执行注意:像第三方库 一般第三方库都使用call来改变 this 的指向。.bind 必须是函数表达式 如果是函数表达式会报错
作用域与作用域链及闭包
JavaScript作用域
- 无块级作用域
- 只有函数和全局作用域
作用域无块级作用域只有函数和全局作用域//无块级作用域if (true) { var name = 'long';}console.log(name);////在高级语言如java 中就会报错。因为 var name = "long";是块级作用域,超出块级作用域范围的console.log(name);会报错而在JavaScript中等同与下面这样(推荐使用)var name;//先定义if (true) { name = "long";}console.log(name);//函数作用域var a = 10000;function fn() { var a = 1000; console.log('fn', a);}console.log("global", a);fn();作用域链eg:var a = 10000;function fn () { var b = 1000; function fn1 () { var c = 100; function fn2 () { var d = 10; console.log(d);//10 console.log(c);//100 自由变量 console.log(b);//1000 自由变量 console.log(a);//10000 自由变量 } d = 20000; fn2(); console.log("1 "+d); } fn1(); console.log("2 "+d);}fn();下面两个例子需要好好思考//dome1var a = 10000;function fn () { var b = 1000; function fn1 () { var c = 100; function fn2 () { var d = 10; console.log(d);//10 console.log(c);//100 自由变量 console.log(b);//1000 自由变量 console.log(a);//10000 自由变量 } fn2(); console.log("1 "+d); d = 20000; } fn1(); d = 30000; console.log("2 "+d);}fn();101001000100001 20000 // ???? 涉及到没有var 定义的变量处理情况。2 30000//dome2var a = 10000;function fn () { var b = 1000; function fn1 () { var c = 100; function fn2 () { var d = 10; console.log(d);//10 console.log(c);//100 自由变量 console.log(b);//1000 自由变量 console.log(a);//10000 自由变量 } fn2(); console.log("1 "+d); d = 20000; } d = 30000; fn1(); console.log("2 "+d);}fn();101001000100001 30000 //函数fn2 里面的值受影响 ????2 20000 //函数fn2 里面的值影响 函数fn1 里面的值 ??? //demo3var a = 100;function fn() { var b = 200; console.log(a);//自由变量(没有找到就去"父级作用域"找) console.log(b);}var b = 20000;fn ();注意 函数外的变量一定不会影响函数里面的变量//demo4var a = 100;function fn() { var b = 200; console.log(a); console.log(b);}b = 20000;fn ();//当前作用域没有定义的变量,即"自由变量"定义 执行闭包function Fn () { var a = 100; //返回一个函数 (函数作为返回值) return function () {// 一个函数的父级作用域是其定义时的作用域 不是 执行时的作用域 console.log(a);//a自由变量,父作用域寻找。 (a此时形成了闭包) (那个作用域定义了他就去那个作用找,一直往上查找) }}// fn 得到一个函数var fn = Fn();var a = 200;//这个a与Fn函数里面的a是两码事fn();//100 // 一个函数的父级作用域是其定义时的作用域 不是 执行时的作用域。如果是看函数fn执行时的作用域那fn()==>200,显然不是,所以只有是看函数fn定义时的作用域那fn() ==> 100 才是正确的//new 才会动用到构造函数里面的thisfunction Fn () { this.name = "123"; var a = 100; //返回一个函数 (函数作为返回值)}// fn 得到一个函数var fn = new Fn();var a = 200;fn.name;//123闭包的使用场景1 函数作为返回值2 函数作为参数传递function Fn () { var a = 100; return function () { console.log(a); }}var fn = Fn();var a = 200;fn();//100function Fn () { var a = 100; return function () { console.log(a);// a 自由变量,父作用域寻找。父作用域是在其声明定义时的作用域,而不是其执行的作用域。本demo中的执行作用域是Fn1的作用域 }}function Fn1 (fn) { var a = 200; fn();}var fn1 = Fn();Fn1(fn1);说一下对变量提升的理解 是执行上下文的概念,变量定义和函数声明(注意和函数表达式的区别) 都会在执行之前 全局作用域 执行前会先确定 变量定义 和 函数声明 函数作用域 执行前会先确定 变量定义 和 函数声明 this arguments创建10个<a>标签 点击的时候弹出来对应的序号//下面的是错误的,十个alert出来的都是9 var i, a; for (i = 0; i < 10; i++) { a = document.createElement('a'); a.innerHTML = i + '<br/>'; a.addEventListener('click', function (e) { e.preventDefault(); alert(i);//i 是自由变量 需要从父级作用域找寻i,但是此时i早就变成了10 (本父级作用域 是全局作用域) }) document.body.appendChild(a) } var i, a; for (i = 0; i < 10; i++) { //自执行函数,就是不用调用,只要定义完成,立即执行的函数 (function (i) {//i 函数作用域 定了就不受外面的影响了 a = document.createElement('a'); a.innerHTML = i + '<br/>'; a.addEventListener('click', function (e) { e.preventDefault(); alert(i);//i 是函数作用的, 需要从父级作用域中寻找 (本父级作用域 是函数作用域);被使用的变量 内存回收机制是不会回收的 }) document.body.appendChild(a) })(i)//形成10个函数 }//下面两个只是改变this的指向又不能形成闭包 var i, a; for (i = 0; i < 10; i++) { function fna () { a = document.createElement('a'); a.innerHTML = i + '<br/>'; a.addEventListener('click', function (e) { e.preventDefault(); alert(i); }); document.body.appendChild(a) } fna.bind({i: i}); fna(); } var i, a; for (i = 0; i < 10; i++) { function fna () { a = document.createElement('a'); a.innerHTML = i + '<br/>'; a.addEventListener('click', function (e) { e.preventDefault(); alert(i); }); document.body.appendChild(a) } fna.call({i: i}); }如何理解作用域链 自由变量 作用域链,即自由变量的查找 闭包的两个两个场景(函数作为返回值,函数作为参数传入)实际开发中闭包的应用 // 闭包实际应用中主要用于封装变量,收敛权限 function isFirstLoad() { var _list = []; return function (id) { if (_list.indexOf(id) >= 0) { return false; } else { _list.push(id); return true; } } } //使用 var firstLoad = isFirstLoad(); firstLoad(10);//true firstLoad(10);//false firstLoad(20);//true //在isFirstLoad 函数外面,根本不可能修改 _list的值
单线程与异步
1 单线线程是对多线程的,对于多线程的开发语言,有一个请求就可以开一个线程处理。那,对于单线程语言,只有通过异步调用程序。【事件 (事件循环机制), 回调】
2 异步是对同步说的, 最大区别就是同步需要等待,异步这不需要等待。
【异步】非阻塞 (function funyb () { console.log(1); setTimeout(function () {console.log(2)}, 3000); console.log(3); })() //1 //3 //2注意: setTimeout(fun,ms);//fun 是一个函数。 比如 function(){console.log(2)}//fun 不能是一个函数执行。 比如 console.log(2) 这样setTimeout的 ms数就没有用了。而是立即执行【同步】会阻塞(function funyb () { console.log(1); alert(2);//这个执行完才会往下。alert 不点击确定就一直不执行console.log(3) console.log(3); })()
会采用异步的三种情况 可以写3个例子分别看看
- 在定时执行时, 如:setTimeout,setInterval
- 请求数据和图片、音频、视频资源时,如 ajax 、img 、audio、video …. 这些资源都要很长的等待时间
- 事件,因为事件只是在用户点击的时候才会触发
!!!需要等待 就异步
!!!需要等待 就异步
!!!需要等待 就异步
注意:闭包容易出现内存泄漏,就是内存空间无法被gc回收。
//10个a标签Array.prototype.slice.call(document.querySelectorAll("a")).forEach(function (item, index) { //在内存中形成10 closest 函数。会占用内存。只是i的值不同0 -> 9 function closest (i) { //代码..... }.bind({i: index}) //父类还没用完 就不能清除 //这两个是一样的 //(function closest (i) { // //代码.... //})(index)})
经典dome
阅读全文
0 0
- JavaScript 三座大山
- javascript基础知识之三座大山
- 专科生头上的“三座大山”
- 新三座大山压垮百姓 忍耐近极限
- 阻碍我学习英语的三座大山
- 搜索引擎优化及百度优化三座大山
- 步入一流企业 CRM助推翻三座大山
- 李易:再谈中国互联网三座大山
- 搬走ERP代理商肩上的“三座大山”
- Linux那些事儿之我是SCSI硬盘(4)三座大山(一)
- Linux那些事儿之我是SCSI硬盘(5)三座大山(二)
- Linux那些事儿之我是SCSI硬盘(6)三座大山(三)
- Linux那些事儿之我是SCSI硬盘(4)三座大山(一)
- java入门三座大山:抽象、封装和多态
- 优秀的产品经理,必须翻越这三座大山
- 不是把BAT“三座大山”斗死了,“农民”就会富起来
- 用 VB 做屏幕监控的三座大山。。。你能克服吗?
- 国内个人android开发者的苦——三座大山压着我们!
- java
- 清华大学2002年机试-对称平方数-1074
- 算法提高 ADV-131 选择排序
- Android Studio基础配置篇
- ActiveMQ的消息存储(八)
- JavaScript 三座大山
- 2017年7月31日-2017年8月25日训练总结
- 算法提高 ADV-132 笨小猴
- 关于Spring
- 算法提高 ADV-134 校门外的树
- Sublime Text 3 快捷键
- iOS学习笔记-094.彩票09——隐藏底部tabar和统一设置返回按钮
- 欧拉函数的一道练习题(附加容斥做法)
- Struts2中的拦截器