俄罗斯女孩制作论文网站,网站开发三大流行语言,自媒体135app下载,学校门户网站的网站建设方案JS三座大山#xff1a;原型和原型连、作用域和闭包、异步和单线程第一篇-----变量类型和计算 参考#xff1a;https://www.jianshu.com/p/8cb184b26ed1题目#xff1a;1.JS中使用typeof能得到哪些类型2.何时使用#xff0c;何时使用3.JS有哪些内置函数4.JS变量按照存储方式… JS三座大山原型和原型连、作用域和闭包、异步和单线程 第一篇-----变量类型和计算 参考https://www.jianshu.com/p/8cb184b26ed1 题目 1.JS中使用typeof能得到哪些类型 2.何时使用何时使用 3.JS有哪些内置函数 4.JS变量按照存储方式分为哪些类型并描述其特点 5.如何理解JSON 知识点##### 值类型vs引用类型 按照存储方式分为值类型和引用类型 引用类型 数组、对象、null、函数。 其他是值类型。 //值类型 var a100 var ba a200 console.log(b) //100 //引用类型 var a{age:20} var ba b.age21 console.log(a.age) //21 引用类型对象、数组、函数由于引用类型占用内存空间较大所以会出现公用内存空间的情况变量a,b是指向某个内存空间的指针。而var ba时其实是b又指向了与a相同的内存空间{age:20}仅存在一份。 typerof运算符详解typeOf有五种基本类型。 typeof undefined //undefined typeof abc //string typeof 123 //number typeof true //boolean typeof {}// object typeof [] // object typeof null // object typeof console.log //function 后四种都是引用类型但typeof只能区分出函数和值类型。 以下情况会发生强制类型转换 字符串拼接 需要慎用会试图进行类型转换使前后相等 if语句var atrue; if(a{ //true } var b 100; if(a){ //true } var a ; if(a){ //false } 逻辑运算符 console.log(10 0) //0 转换为true0 console.log(||abc) //abc 转换为false||abc console.log(!window.abc) //true !undefined为true undefined 和 is not defined 不同后者是报错前者是未定义 解题##### 1.JS中使用typeof能得到哪些类型 undefined,string,number,boolean,object,function 2.何时使用何时使用 //仅有这种情况使用 if(obj.anull){ //此时条件相当于obj.anull||obj.aundefined,简写形式 //这是jQuery源码中推荐的写法 } 除此之外其它情况均建议使用 3.JS有哪些内置函数 Object,Array,Boolean,Number,String,Function,Date,RegExp,Error 4.JS变量按照存储方式分为哪些类型并描述其特点 分为值类型和引用类型值类型可以将数据分块存储在内存中但是引用类型是多个变量共用一个内存块引用类型的赋值是指定了一个指针并不是真正的值的拷贝它们之间是会相互干预的。 5.如何理解JSON JSON是JS中的一个内置对象也是一种数据格式 JSON.stringify({a:10,b:20}) //将对象转换为字符串 JSON.parse({a:10,b:20}) //把字符串转换为对象 第二篇-----原型与原型链 参考https://www.jianshu.com/p/dc3015d68c46 题目 1.如何准确判断一个变量是数组类型 2.写一个原型链继承的例子 3.描述new一个对象的过程 4.zepto框架中如何使用原型链 知识点 构造函数function Foo(name,age){ this.namename this.ageage this.classclass-1 //return this //默认有这一行 } var fnew Foo(zhangsan,20) //var f1new Foo(lisi,22) //创建多个对象 构造函数-扩展var a{} //其实是var anew Object()的语法糖 var b[] //其实是var bnew Array()的语法糖 function Foo(){...} //其实是var Foonew Function(...) 使用instanceof判断一个函数是否是一个变量的构造函数 所有的引用类型对象、数组、函数都有构造函数a的构造函数是Object()b的构造函数是Array()Foo的构造函数是Function()。所以假如想要判断一个变量是否为数组就可以使用 var a{} a instanceof Array //false 原型规则和实例熟记所有的引用类型都具有对象特性即可自由扩展属性null除外所有引用类型都有一个__proto__隐式原型属性属性值是一个普通的对象所有函数都有一个prototype 显式原型属性属性值也是一个普通的对象所有引用类型的__proto__属性值指向它的构造函数的prototype的属性值当试图得到一个引用类型的某个属性时如果这个对象本身没有这个属性那么会去它的__proto__(即它构造函数的prototype)中寻找var obj{};obj.a100;var arr[];arr.a100;function fn(){}fn.a100console.log(obj.__proto__)console.log(arr.__proto__)console.log(fn.__proto__)console.log(fn.prototype)console.log(obj.__proto__Object.prototype) //true //构造函数 function Foo(name,age){ this.namename } Foo.prototype.alertNamefunction(){ //由于prototype是一个普通对象所以也可以扩展属性 alert(this.name) } //创建实例 var fnew Foo(zhangsan) f.printNamefunction(){ console.log(this.name) } //测试 f.printName() //zhangsan f.alertName() //f没有alertName属性,于是去f._proto_即Foo.prototype中查找 由对象调用原型中的方法this指向对象 //循环对象自身的属性 var item //理论上有三个属性 name, printName,alertName 。但是自身的属性只有前两个使用hasOwnProperty() 能过滤掉原型上的属性 for(item in f){ //高级浏览器已在for in中屏蔽了来自原型的属性 //但是这里建议还是加上这个判断以保证程序的健壮性 if(f.hasOwnProperty(item)){ console.log(item) } } 原型链//在刚刚的代码中加入 f.toString() //要去f.__proto__.__proto__中查找 找到了 所有的引用类型都有__proto__属性且__proto__属性值指向它的构造函数的prototype的属性值所以当f不存在toString时便会在f.__proto__即Foo.prototype中查询而Foo.prototype中也没有找到toString。由于Foo.prototype也是一个对象所以它隐式原型__proto__的属性值便指向它的构造函数Object的prototype的属性值。 一个函数都会有显式原型属性属性值是一个普通对象见原型规则3。而普通对象的构造函数是Object //试一试 console.log(Object.prototype) console.log(Object.prototype.__proto__) //为了避免死循环所以此处输出null 原型链 instanceof用于判断引用类型属于哪个构造函数的方法f instanceof Foo //true判断逻辑是f的__proto__一层层向上能否对应到Foo.prototype再试着判断 f instanceof Object //true 解题##### 1.如何准确判断一个变量是数组类型 使用instanceof (用于判断引用类型属于哪个构造函数的方法) var arr[] arr instanceof Array //true typeof arr //object typeof无法准确判断是否是数组 2.写一个原型链继承的例子 //简单示例比较low下面有更贴近实战的例子 //动物 function Animal(){ this.eatfunction(){ console.log(Animal eat) } } //狗 function Dog(){ this.barkfunction(){ console.log(Dog bark) } } Dog.prototypenew Animal() //哈士奇 var hashiqinew Dog() //更贴近实战的原型继承实例 //封装一个DOM查询 function Elem(id){ this.elemdocument.getElementById(id); } Elem.prototype.html function(val){ if(val){ this.elem.innerHTML val; } return this; } Elem.prototype.onfunction(type,fn){ var elemthis.elem; elem.addEventListener(type,fn); return this; //链式操作 } var div1new Elem(div1); // console.log(div1.html()); // div1.html(pHello/p); // div1.on(click,function(){ // alert(clicked) // }); div1.on(click,function(){ alert(clicked); }).html(p链式操作/p); //在之前的函数中增加了return this由div1调用时便会返回当前对象即div1便可以实现链式操作 3.描述new一个对象的过程 function Foo(name,age){ // this{} this.namename; this.ageage; this.classclass-1; //return this; //默认有这一行 } var fnew Foo(zhangsan,20); //var f1new Foo(lisi,22); //创建多个对象 过程 创建一个新对象 //{} this指向这个新对象 this{} 执行代码即对this赋值 this.xxxxxx 返回this return this 4.zepto框架如何使用原型链 第三篇-----作用域和闭包 题目 1.说一下对变量提升的理解 2.说明this几种不同的使用场景 3.创建10个a标签点击时弹出对应序号 4.如何理解作用域 5.实际开发中闭包的应用 知识点##### 执行上下文 范围一段script或者一个函数 或者eval代码 全局变量定义、函数声明 提前拿出来 针对一段script 函数变量定义、函数声明、this、arguments 提前拿出来 针对一个函数 eval不常用也不推荐大家用。 在一段js代码拿过来真正一句一句运行之前浏览器已经做了一些“准备工作”在“准备工作”中完成了哪些工作 1.变量、函数表达式——变量声明默认赋值为undefined 2.this——赋值 3.函数声明——赋值 这三种数据的准备情况我们称之为“执行上下文”或者“执行上下文环境”。 ps注意函数声明和函数表达式的区别 //函数声明 function fn(){ //..... } //函数表达式 var fn1function(){ //..... } //全局console.log(a); //undefined var a100 fn(zhangsan) //zhangsan 20 function fn(name){ //函数 console.log(this); //Window console.log(arguments); //zhangsan age20 console.log(name,age); var age //age会提前 } this this要在执行时才确认值定义时无法确认 var a{ name:A, fn:function(){ console.log(this.name); } } a.fn() //thisa a.fn.call({name:B}) //this{name:B} var fn1a.fn fn1() //thisWindow - 作用域 js没有块级作用域 if(true){ var namezhangsan } console.log(name); //zhangsan 只有函数和全局作用域 var a100 function fn(){ var a200 console.log(fn,a) } console.log(global,a) //global 100 fn() //fn 200 作用域链 自由变量 var a100 function fn(){ var b200 console.log(a) //当前作用域没定义的变量即自由变量 console.log(b) } fn() //100 200 调用在当前作用域不存在的变量便会向父级作用域查找。需要注意的是父级作用域是函数定义时产生的并非函数调用时。 var a100 function F1(){ var b200 function F2(){ var c300 console.log(a) //a是自由变量在F2中未找到便向父级作用域F1查找仍未找到继续向上查找在Window中找到 console.log(b) //b是自由变量 console.log(c) } F2() } F1() //100 200 300 - 闭包使用场景函数作为返回值函数作为参数传递 //闭包的使用场景函数作为返回值 function F1(){ var a100 //返回一个函数 return function(){ console.log(a) //自由变量父作用域查找仍未找到继续向上查找在Window中找到 } } //f1得到一个函数 var f1F1() var a200 f1() //100 //闭包的使用场景函数作为参数传递 function F1(){ var a100 return function(){ console.log(a) //自由变量父作用域查找 } } var f1F1() function F2(fn){ var a200 fn() } F2(f1) //100 #####解题##### **1.说一下对变量提升的理解** 在ES6之前JavaScript没有块级作用域(一对花括号{}即为一个块级作用域)只有全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。 在script或函数中各个变量、函数的声明与定义会被提前 执行上下文。变量、函数表达式、this、函数声明这几种数据的准备情况称之为“执行上下文” **2.说明this几种不同的使用场景** this的几种执行情况 作为构造函数执行作为对象属性执行作为普通函数执行call apply bind//构造函数 function Foo(name){ this.namename } var fnew Foo(zhangsan) //对象属性 var obj{ name:zhangsan, printName:function(){ console.log(this.name) } } obj.printName() //普通函数 function fn(){ console.log(this); } fn() //window //call apply bind function fn1(name,age){ alert(name) console.log(this) } fn1.call({x:100},zhangsan,20) //({x:100} //apply fn1.apply({x:100},[zhangsan,20]) //({x:100} call, apply方法区别是,从第二个参数起, call方法参数将依次传递给借用的方法作参数, 而apply直接将这些参数放到一个数组中再传递 //bind var fn2function (name,age){ //bind在函数声明的形式后不可用必须是函数表达式 alert(name) console.log(this) }.bind({y:200}) fn2(zhangsan,20) //{y: 200} **3.创建10个a标签点击时弹出对应序号** //错误的写法 var i,a; for(i0;i10;i){ //除了click函数内部都为全局作用域会被覆盖。因此最终 i 的值为10 //全局作用域 a document.createElement(a); a.innerHTML i/br ; a.addEventListener(click,function(e){ e.preventDefault(); alert(i); //i为自由变量向上去父作用域查找时值已经变成10. 因为click事件执行时其它部分早已执行完毕。 }) document.body.appendChild(a); } //正确的写法 var i for(i0;i10;i){ //多包了一层除了click函数其它变量的作用于都变成了函数作用域而不是全局作用域因此不会被覆盖。相当于创建了10个函数 (function(i){ //函数作用域 var adocument.createElement(a) a.innerHTMLi a.addEventListener(click,function(e){ e.preventDefault() alert(i) //i为自由变量向上去父作用域查找就找到调用时的i值 加粗处 }) document.body.appendChild(a) })(i) } 工作实例 不用闭包 结果永远是i的最大值1因此必须使用闭包 **4.如何理解作用域** 回答要点 自由变量 //当前作用域没定义的变量即自由变量 作用域链即自由变量的查找 闭包的两个场景 **5.实际开发中闭包的应用** //闭包实际应用中主要用于封装变量收敛权限 function isFirstLoad(){ var _list[] return function(id){ if(_list.indexOf(id)0){ return false }else { _list.push(id) return true } } } //使用 var firstLoadisFirstLoad()9 firstLoad(10) //true firstLoad(10) //false firstLoad(20) //true //在isFirstLoad函数外无法修改_list的值 第四篇 异步和单线程 题目 1.同步和异步的区别是什么分别举一个同步和异步的例子 2.一个关于setTimeout的笔试题 3.前端使用异步的场景有哪些 知识点##### 什么是异步对比同步//异步 console.log(100); setTimeout(function(){ console.log(200); },1000) console.log(300); // 100 // 300 // 1s后 200 //同步 console.log(100); alert(200); console.log(300); //100 //对话框200 //关闭对话框后300 同步会出现阻塞alert(200)不执行结束后面的代码不会继续执行 - 前端使用异步的场景 在可能发生等待的情况。 等待的过程中不能像alert一样阻塞程序运行 因此所有的“等待的情况”都需要异步执行。 -1) 定时任务setTimeout、setInterval -2) 网络请求ajax请求动态img加载等 -3) 事件绑定 //ajax请求 console.log(start); $.get(data/data1.json,function(data1){ console.log(data1); }) console.log(end); //start //end //数据 //图片加载 console.log(start); var imgdocument.createElement(img) img.οnlοadfunction(){ console.log(loaded); } img.srcimages/icon.jpg document.body.appendChild(img) console.log(end); //start //end //loaded //事件绑定 console.log(start); document.getElementById(btn1).addEventListener(click,function(){ console.log(clicked) }) console.log(end); //start //end //点击打印clicked - 异步和单线程 console.log(100); setTimeout(function(){ console.log(200); }) //未设置等待时间 console.log(300); //100 //300 //200 - 执行第一行打印100 - 执行setTimeout后传入setTimeout的函数会被暂存起来不会立即执行单线程的特点不能同时执行两个任务 - 执行最后一行打印300 - 待所有任务执行完处于空闲状态才执行暂存的任务 - 暂存的setTimeout无等待时间立即执行 #####解题##### **1.同步和异步的区别是什么分别举一个同步和异步的例子** - 同步与异步最大的区别是阻塞代码同步会阻塞代码而异步不会 - alert是同步setTimeout是异步 **2.一个关于setTimeout的笔试题** console.log(1); setTimeout(function(){ console.log(2); },0) console.log(3); setTimeout(function(){ console.log(4); },1000) console.log(5); //1 //3 //5 //2 //1s后 4 **3.前端使用异步的场景有哪些** - 定时任务setTimeout、setInterval - 网络请求ajax请求动态img加载 - 事件绑定 它们共同的特点是需要等待由于js是一个单线程语言为了避免阻塞所以要使用异步 第五篇 其它知识点(如date、Math、常用API) 1.获取2017-07-13格式的日期 //日期 2.获取随机数要求是长度一致的字符串格式 //Math 3.写一个能遍历对象和数组的通用forEach函数 //数组API 对象API 知识点##### 日期Date.now() //获取当前时间毫秒数 var dtnew Date() dt.getTime()//获取毫秒数 dt.getFullYear() //年 dt.getMonth()//月(0-11) dt.getDate() //日(0-31) dt.getDay() //星期(0 代表星期日 1 代表星期一2 代表星期二 依次类推) dt.getHours() //小时(0-23) dt.getMinutes() //分钟(0-59) dt.getSeconds()//秒(0-59) //获取的一切时间都是var dtnew Date()时的时间 Math 获取随机数Math.random() 数组API 1forEach遍历所有元素 var arr[1,2,3] arr.forEach(function(item,index){ // forEach() 方法对数组的每个元素执行一次提供的函数 console.log(index,item); }) //0 1 //1 2 //2 3 2) every判断所有元素是否符合条件 var arr[1,2,3] var resultarr.every(function(item,index){ //every() 方法测试数组的所有元素是否都通过了指定函数的测试(所有所有) if(item4){ return true } }) console.log(result); //true 3) some 判断是否至少有一个元素符合条件 var arr[1,2,3] var resultarr.some(function(item,index){ //some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试只需有一个满足条件即返回true if(item2){ return true } }) console.log(result); //true 4) sort 排序 var arr[1,4,2,3,5] var arr2arr.sort(function(a,b){ //arr.sort()默认从小到大排序 //从小到大排序 return a-b //从大到小排序 // return b-a }) console.log(arr2:arr2); //arr2:1,2,3,4,5 5) map 对元素重新组装生成新数组 var arr[1,2,3,4,5] var arr2arr.map(function(item,index){ //将元素重新组装并返回 return bitem/b }) console.log(arr2); // [b1/b, b2/b, b3/b, b4/b, b5/b] 6) filter 过滤符合条件的元素 var arr[1,2,3,4,5] var arr2arr.filter(function(item,index){ // filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素 if(item3){ return true } }) console.log(arr2); // [3, 4, 5] 对象APIvar obj{ x:100, y:200, z:300 } var key for(key in obj){ //hasOwnProperty会返回一个布尔值判断是否是原生的属性以此来排除原型链上的属性 if(obj.hasOwnProperty(key)){ console.log(key,obj[key]); } } //x 100 //y 200 //z 300 解题##### 1.获取2017-07-13格式的日期 function formatDate(dt){ if(!dt){ dtnew Date(); } var yeardt.getFullYear() var monthdt.getMonth()1 var datedt.getDate() if(month10){ month0month } if(date10){ date0date } return year-month-date } var dt dtnew Date() alert(formatDate(dt)) 2.获取随机数要求是长度一致的字符串格式 var randomMath.random() var randomrandom0000000000 //10个0 var randomrandom.slice(0,10) //slice() 方法返回一个从0开始到1结束(不包括结束)选择的数组的一部分,浅拷贝到一个新数组对象。原始数组不会被修改console.log(random); 3.写一个能遍历对象和数组的通用forEach函数 function myForEach(obj,fn){ var key if(obj instanceof Array){ //判断是否为数组 obj.forEach(function(item,index){ fn(index,item) }) }else{ //不是数组就是对象 for(key in obj){ fn(key,obj[key]) } } } var arr[1,2,3] //参数顺序换了为了和对象的遍历格式一致 myForEach(arr,function(index,item){ console.log(index,item); }) var obj{x:100,y:200} myForEach(obj,function(key,value){ console.log(key,value); }) //0 1 //1 2 //2 3 //x 100 //y 200 转载于:https://www.cnblogs.com/morongwendao/p/9585052.html