多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## JS基础知识 ### 变量类型和计算 1. js中typeof能得到哪些类型 2. 何时使用===何时使用== 3. js中有哪些内置函数 4. js变量按照存储方式区分为哪些类型,特点 5. 如何理解JSON ### 知识点 1. 变量类型 * 值类型vs引用类型 ~~~ var a={age:18}; var b=a; b.age = 28; console.log(a.age)//28 存储的是对象的地址(指针) ~~~ **引用类型:对象,数组,函数**,特点:**无限制扩展属性**(函数和数组都可以有属性!),属性过多时,内存占用会大,把b赋值成a,若b也占很大空间,这是不合理的,所以,**为了让内存中共用空间**。 * 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 null//object**//空指针,定义了一个位置,但并没有指向任何引用位置的真事的对象 **typeof console.log //function** **typeof只能区分值类型的详细类型(undefined,string,number,boolean),针对引用类型不行,区分不出来,只能区分出函数引用类型(function)**,函数是非常特殊的引用类型,在js中函数定位非常高,因此在任何时候需要把函数类型区别出来 2. 变量计算 强制类型转换 * 字符串拼接 ~~~ var b = 100 + "10";//10010 ~~~ * ==运算符 ~~~ 100 == '100'//true 0 == '' //true 都转为false null == undefined//true 都转为false ~~~ ==运算符慎用 换成=== 都会false * if语句 ~~~ var b=100 if(b){} var c='' if(c){} ~~~ if会将变量强制转换为boolean类型 **会是fasle :0,NaN,'',null,undefined,false** * 逻辑运算 ~~~ 10 && 0 //返回0 '' || 'abc' //返回'abc' !window.abc //true var a = 100; !!a//true ~~~ 判断一个变量会被当做true还是false ### 解答 1. js中typeof能得到哪些类型 **undefined string number boolean object function** 能把值类型区分出来,引用类型区分不了太细(function) null(object) 2. 何时使用===何时使用== ~~~ if(obj.a == null){ //相当于obj.a===null || obj.a ===undefined 简写形式 //这是jquery源码中推荐的写法 } ~~~ **除了obj.a == null(对象的属性是否存在)这个之外,其他全部用 ===** **function(a,b){if(a == null){}}//函数的参数是否存在也用双等** (代码洁癖,必须用 ===) 3. js中有哪些内置函数--**数据封装类对象** **Object,Array,Boolean,Number,String,Function,Date,RegExp,Error**,注意,**都是函数!!** **Math是对象**,不是函数 内置函数作用:作为构造函数的作用。。。 4. js变量按照存储方式区分为哪些类型,特点 值类型和引用类型 **值类型:把数据分块存在内存中** **引用类型:好几个变量公用一个内存块,节省内存空间** 特点(区别):**值类型的值赋值不会相互干涉,引用类型,赋值是变量指针的赋值,并不是真正值的拷贝,值的修改是相互干预的。** 5. 如何理解JSON JSON只不过是一个**js对象**而已(js的内置对象,和Math一样,不是函数)(也是一种数据格式)(有两个api) ~~~ JSON.stringify({a:100}) JSON.parse('{'a':10}') ~~~ 如果使用JSON.parse()方法来转化成json对象的数据格式的话,需要注意的是**被转化的字符串里面的属性要使用引号,并且总体是单引号套双引号的方式**。 JSON.stringify智能化体现 * 键名不是双引号(没有引号,单引号),都会自动变成双引号,字符串是单引号,会自动变成双引号 * 最后一个属性后面有逗号,会自动去掉 * 非数组对象的属性不能 保证以特定的属性出现在序列 后的字符串中 * 布尔值、数字、字符串的**包装对象**在序列化过程中汇报自动转换成对应的**原始值** (new String('bala')==>bala)(new Number(2017)==>2017) * **undefined、任意的函数,以及symbol值,出现在非数组对象的属性中,在序列化过程中会被忽略;出现在数组中时,被转化成null,NaN,Infinity,-Infinity无论在数组还是非数组中,都被转为null** ~~~ JSON.stringify({x:undefined,y:function(){},z:Symbol('')}) //{} JSON.stringify([undefined,function(){},Object,Symbol("")]) //[null,null,null,null] ~~~ ### 原型和原型链 #### 题目 1. 如何准确判断一个变量是数组类型(typeof不行) 2. 写一个原型链继承的例子 3. 描述new一个对象的过程 4. zepto(或其他框架)源码中如何使用原型链 #### 知识点 1. 构造函数 2. 构造函数-扩展 3. 原型规则和示例 4. 原型链 5. instanceof ##### 构造函数 特点:基本大写字母开头的函数 ~~~ function Foo(name,age){ this.name = name; this.age = age; this.class="class-1" //return this;//默认有这一行 } var f = new Foo("zhangsna",20)//创建多个对象 ~~~ ##### 构造函数 - 扩展 1. var a = {};其实是var a = new Object()的语法糖(构造函数是Object) 2. var a=[];其实是var a= new Array()的语法糖(构造函数是Array) 3. function Foo(){...}其实是var Foo = new Function(){}(构造函数是Function) 4. **使用instanceof判断一个函数是否是一个变量的构造函数** **所有的引用类型都有构造函数!** **判断一个变量是否为“数组”:变量instanceof Array** ##### 原型规则和示例 5条原型规则 **原型规则是学习原型链的基础** 1. 所有的引用类型(数组,对象,函数),都具有**对象特性,即可自由扩展属性**(除了null(是引用类型,但...)例外) ~~~ var obj ={}; obj.a=100; var arr=[]; arr.a =100; function fn(){} fn.a =100; ~~~ 2. 所有的引用类型(数组,对象,函数),都有一个__proto__(隐式原型)属性,属性值是一个普通的对象 ~~~ console.log(obj.__proto__); console.log(arr.__proto__); console.log(fn.__proto__); ~~~ 3. 所有的函数,都有一个prototype(显示原型)属性,属性值也是一个普通的对象 ~~~ console.log(fn.prototype) ~~~ 4. **所有的引用类型(数组,对象,函数),__proto__属性值指向它的构造函数的“prototype”属性值** ~~~ console.log(obj.__proto__ === Object.prototype) ~~~ 5. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,**那么会去它的__proto__(即它的构造函数的prototype)中寻找** ~~~ function Foo(name,age){ this.name = name; } Foo.prototype.alertName = function(){ alert(this.name) } var f= new Foo('张三') f.printName = function(){ console.log(this.name); } f.printName(); f.alertName(); ~~~ #### this(对象自身) #### 循环对象自身的属性 ~~~ var item; for(item in f){ //高级浏览器已经在for in中屏蔽了来自原型的属性 //但是这里建议大家还是加上这个判断,保证程序的健壮性 if(f.hasOwnProperty(item){ console.log(item); }) } ~~~ #### 原型链 ~~~ f.toString();//要去f.__proto__.__proto__中查找 ~~~ ![](images/IMG_5963.PNG) ![](images/IMG_5964.PNG) null是特例,避免死循环 #### instanceof **用于判断引用类型属于哪个构造函数的方法** 1. f instanceof Foo的判断逻辑是: * f的__proto__一层一层往上,能否对应到Foo.prototype 2. 再判断f instanceof Object ### 解题 1. 如何准确判断一个变量是数组类型(typeof不行) instanceof toString 2. 写一个原型链继承的例子 ~~~ //动物 function Animal(){ this.eat = function(){console.log('animal eat')}; } //狗 function Dog(){ this.bark = function(){ console.log('dog bark'); } } Dog.prototype = new Animal(); //土狗 var bomei = new Dog(); bomei.eat(); bomei.bark(); ~~~ ~~~ 写一个封装dom查询 function Elem(id){ this.elem = document.getElementById(id); } Elem.prototype.html = function(val){ var elem = this.elem; if(val){ elem.innerHTML = val; return this;//返回对象 为了链式操作 }else{ return elem.innerHTML; } } Elem.prototype.on = function(type,fn){ var elem = this.elem; elem.addEventListener(type,fn); return this; } var div1 = new Elem('div1') console.log(div1.html());//打印div的内容 div1.html('') div1.html('<p>哈哈哈</p>'); div1.on('click',function(){ alert('click') }) //链式操作 div1.html('<p>哈哈哈</p>').on('click',function(){ alert('click') }).html(''); ~~~ 这个比较low,不要这么写,要更贴近实战的 3. 描述new一个对象的过程 * 创建一个新对象 * this指向这个新对象 * 执行代码,即对this赋值 * 返回this 4. zepto(或其他框架)源码中如何使用原型链 * 阅读源码是高效提高技能的方式 * 不能埋头苦钻,技巧,可以先查看资料(源码分析,铺垫) * 慕课网 zepto设计和源码分析(阅读体会,收益) ### 作用域和闭包 #### 作用域 jQuery源码中,代码包在(function(){})()中:目的是希望里面所有的变量,不会暴露在外面,**以防止变量全局污染,这就是函数作用域**。 在JS中,变量的作用域有两种:全局作用域和函数作用域。ES6中有了块级作用域的概念(let和const定义即可) 1. 全局作用域 * 没有var声明的变量(除去函数的参数),都具有全局作用域,成为全局变量 * window的所有属性都具有全局作用域 * 最外层函数体外声明的变量也具有全局作用域(可以被任何函数访问) ~~~ var data= {name:'peter'}; (function f1(){console.log('data',data)})() ~~~ 坏处:变量间很容易产生冲突(同名变量) ~~~ var data = {name:"peter"};//A定义 //省去100行代码 var data = {name:"lily"};//B定义 ~~~ 2. 函数作用域 在函数作用域中定义的变量,在函数外部是无法访问的(报错) ~~~js function f1(){ var data={name:"peter"} } console.log('data',data)//Uncaught ReferenceError: data is not defined ~~~ 3. ES6块级作用域 任何一对花括号({})中的语句都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,称之为块级作用域 * let声明的变量,只在let所在的代码块有效,在代码块外调用let会报错 ~~~ { var a={name:'peter'}; let b= {name:"lily"}; console.log(a,b);//输出 } console.log(a)//{name:'peter'} console.log(b)//报错Uncaught ReferenceError: b is not defined ~~~ ~~~ console.log(a);//undefined var a=1; console.log(a)//1 ~~~ * 变量不存在提升,使用let命令声明的变量,只能在声明后使用(暂时性死区) * 使用const声明的变量不能再次赋值(对象除外) 2. 变量提升,函数提升 ~~~ console.log('f1',f1); function f1(){ console.log("enter f1"); } var f1 = 1; ~~~ !!结果: ~~~ function f1(){ console.log("enter f1"); } ~~~ 可见:打印出f1函数,不是undefined,不是1,说明:**函数提升优于变量提升**,会优先处理函数声明,再处理变量声明。 若声明的变量和声明的函数重名,则变量的声明不会影响函数的声明。 #### 小结 1. **使用var声明的变量存在变量提升**,即可在声明变量之前使用变量,使用let,const声明的变量不能在声明变量之前使用 2. **函数提升优先于变量提升,函数提升会被整个函数挪到作用域顶部,变量提升会被变量声明挪到作用域顶部** ### 作用域链 要得到一个变量的值,若当前作用域没有定义,就到父级作用域寻找,如果父级作用域中也没找到,就再想上一层寻找,直到找到全局作用域。这一层一层的关系,就是作用域链 ~~~ var data = { name : 'guo'}; (function f1(){ var a = 1; (function f2(){ var b= 2; console.log(data)//向上顺着作用域找 console.log(a)//向上顺着作用域找 console.log(b)//当前作用域 console.log(c);//没找到,报错 })() })() ~~~ ### 函数声明和函数表达式 ~~~ fn();// function fn(){ //函数声明(全局函数处理) } var fn = function(){ //函数表达式 } ~~~ ~~~ console.log(fn)//函数 fn();//xxx function fn(){ console.log('xxx') } console.log(fn1)//undefined (把var fn1提前,并赋值undefined) fn1();//报错 var fn1 = function(){ console.log('yyy') } ~~~ ~~~ fn('ye'); function fn(name){ age = 20; console.log(name) console.log(age);//20; var age; } ~~~ 1. 全局script标签(每个script标签里,变量函数声明都会提前) 2. 函数执行内部会把函数,变量声明提前(this,arguments,执行时方只是什么) ~~~ <script> console.log(guo) //报错 </script> <script> console.log(guo) //undefined var guo = 100; </script> ~~~ ### 作用域和闭包 1. 说一下对变量提升的理解 2. 说明this几种不同的使用场景 3. 创建10个<a>标签,点击是弹出来对应的序号 4. 如何理解作用域 5. 实际开发中闭包的应用 ### 知识点 #### 执行上下文 ~~~ console.log(a);//undefined var a= 100; fn('guo');//guo 20 function fn(name){ age = 20; console.log(name,age); var age; } ~~~ 1. 范围:一段`<script>`或者一个函数(都会生成一个执行上下文) 2. 全局:(先去)变量定义、函数声明 (一段`<script>`) 3. 函数:变量定义,函数声明,this,arguments (函数) 4. 注意函数声明和函数表达式的区别(**函数声明直接把整个函数提前,函数表达式只把函数名称提前,并赋值undefined**) #### this 1. this要在执行时才能确认值,定义时无法确认(js不是编译语言,是执行语言,如果函数有错,什么时候执行,什么时候报错) ~~~ var a = { name:'a', fn: function(){ console.log(this.name) }}; a.fn();//a a.fn.call({name:'b'});//b var fn1= a.fn; fn1();//undefined this指向window ~~~ 2. 作为构造函数执行 ~~~ function Foo(name){ //this = {}; this.name = name; //return this; } var f = new Foo('张三') ~~~ 3. 作为对象属性执行 ~~~ var obj = { name:'a', printName:function(){ console.log(this.name) } } obj.printName(); ~~~ 4. 作为普通函数执行 ~~~ function fn(){ console.log(this); // this === window } ~~~ 5. call apply bind ~~~ function fn1(name,age){ alert(name); console.log(this); } fn1.call({x:300},“郭”)//第一个参数是绑定的对象(this),第二个参数才是传入方法的第一个参数 ~~~ ~~~ var fn2 = function(name,age){ alert(name); console.log(this); }.bind({y:200}) fn2.(“郭”)//第一个参数是绑定的对象(this),第二个参数才是传入方法的第一个参数 ~~~ **.bind必须是一个函数表达式,而不是函数声明**!!call比较常用,apply用的相对较少 call:和apply的意思一样,只不过是参数列表不一样. Person.apply(this,arguments);arguments是数组 Person.call(this,name,age);后面是参数 #### 作用域 1. js没有块级作用域 ~~~ if(true){ var name = "xxx" } console.log(name) //能访问到,且xxx ~~~ ~~~ if(false){ var name = "xxx" } console.log(name) //能访问到,undefined ~~~ ~~~ if(false){ name = "xxx" } console.log(name) //报错 ~~~ 2. 只有函数和全局作用域 ~~~ var a = 100; function fn(){ var a = 200; console.log(a);//200 函数作用域 a和外部隔绝 } console.log(a)//100 全局作用域 fn(); ~~~ jQuery ,zepto等第三方库,如何保证自己的变量不会被污染:**把所有的变量都定义在一个大的函数里** #### 作用域链 **自由变量**:当前作用域没有定义的变量 ~~~ var a = 100; function fn(){//此时父级作用域是全局作用域 var b = 200; console.log(a);//当前作用域没有定义的变量,即“自由变量” console.log(b) } fn(); ~~~ **函数父级作用域**:**函数定义的地方**,父级作用域在哪儿,不是函数执行的地方 ~~~ var a = 100; function F1(){ var b=200; function F2(){//F2的父级定义域是F1 var c= 300; console.log(a); //a是自由变量 F2==>F1==>全局 console.log(b);//b是自由变量 console.log(c); } } ~~~ #### 闭包 ~~~ function F1(){ var a =100; //父级作用域 //返回一个函数(函数作为返回值) return function(){ console.log(a); //a是自由变量 去父级作用域中去寻找 } } //f1得到一个函数 var f1 = F1(); var a = 200; //修改的是全局作用域,不是F1的 f1();//100 ~~~ **!!一个函数的作用域,是它定义时的作用域,而不是它执行时的作用域!!**。 #### 闭包的使用场景 1. 函数作为返回值(上一个demo) 2. 函数作为参数传递 ~~~ function F1(){ var a =100; //父级作用域 //返回一个函数(函数作为返回值) return function(){ console.log(a); //a是自由变量 去父级作用域中去寻找 } } var f1 = F1(); function F2(fn){ var a = 200;//F2的作用域,不是F1的作用域 fn(); } F2(f1)//100 ~~~ #### 解题 1. 说一下变量提升 * 变量的定义 * 函数声明(和函数表达式的区别) 2. this应用场景 * 作为构造函数执行 * 对象属性 * 普通函数 * call apply bind 3. 创建10个`<a>`标签,点击是弹出对应的序号 ~~~ 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 自由变量 属于全局作用域,已经发生更改 均输出10 }) document.body.appendChild(a) } ~~~ 正确写法 ~~~ var i; for(i=0;i<10;i++){ (function(i){ var a = document.createElement('a'); a.innerHTML = i+"<br>"; a.addEventListener('click',function(e){ e.preventDefault(); alert(i) //自由变量,是自执行函数作用域的i,不是全局作用域,生成了10个函数, }) document.body.appendChild(a) })(i) } ~~~ 分析:点击的时候,i是自由变量,先找父级作用域,父级作用域是一个函数,函数创建的时候,i是当时传入的值 4. 如何理解作用域 * 自由变量 * 作用域链,即自由变量的查找 * 闭包的两个场景(函数作为返回值,函数作为参数) 5. 实际开发中闭包的应用 **用于封装变量,收敛权限** ~~~ function isFirstLoad(){ var _list = [];//下划线,私有 return function(id){ if(_list.indexOf(id) === 0){ return false; }else{ _list.push(id) return false; } } } var firstLoad = isFirstLoad(); firstLoad(10); // true firstLoad(10); //false firstLoad(20); //true ~~~ 分析:你在isFirstLoad函数外面,根本不可能修改掉_list的值 **自执行函数**:不用调用,只要定义完成,立即执行的函数 ### 异步和单线程 #### 题目 1. 同步和异步的区别是什么?举例 2. setTimeout笔试题 3. 前端使用异步的场景 #### 知识点 1. 什么是异步(对比同步) 2. 前端使用异步的场景 3. 异步和单线程 ***** 1. 什么是异步 ~~~ console.log(100) setTimeout(function(){ console.log(200) },1000) console.log(300) //100 300 200 ~~~ 对比同步 ~~~ console.log(100); alert(200); console.log(300) //不确认,就不会往下执行,会阻塞程序执行,异步不会卡顿,阻塞 ~~~ 2. 何时需要异步(不能卡顿) * 在可能发生等待的情况 * 等待过程中不能像alert一样阻塞程序运行 * 所有的“等待的情况”,需要异步 3. 使用异步的场景(不能卡顿) * 定时任务:setTimeout,setInterval * 网络请求:ajax强求,动态`<img>`加载 * 事件绑定(不知道什么时候触发)(click,keyup keydown) ~~~ console.log('start'); var img = document.createElement('img'); img.onload = function(){console.log('loaded')} img.src="xxx" console.log('end') ~~~ #### 异步和单线程 ~~~ console.log(100) setTimeout(function(){ console.log(200) },1000) 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) },0) console.log(5) //1 3 5 2 4 ~~~ 3. 前端使用异步的场景 特点:需要等待,不能阻塞(单线程) * 定时任务:setTimeout ,setInterval * 网络请求:ajax请求 ,动态img加载 * 事件绑定 ### 其他知识 #### 题目 1. 获取 2017-06-10格式的日期 2. 获取随机数,要求是长度一致的字符串格式 3. 写一个能遍历对象和数组的通用forEach函数 #### 知识点 1. 日期 ~~~ Date.now();//毫秒数 var dt = new Date();//时间标准格式,不符合国内需求 dt.getTime();//毫秒数 dt.getFullYear();//年 dt.getMonth();//月(0-11) dt.getDate();//日(0-31) dt.getHours();//小时(0-23) dt.getMinutes();//分钟(0-59) de.getSeconds();//秒(0-59) ~~~ ~~~ getFormateDate(date){ if(!date){ date = new Date()} var y = date.getFullYear(); var M = date.getMonth()+1; var d = date.getDate(); var h = date.getHours(); var m = date.getMinutes(); var s = date.getSeconds(); M = M>9?M:'0'+M; d = d>9?d:'0'+d; h = h>9?h:'0'+h; m = m>9?m:'0'+m; s = s>9?s:'0'+s; return y+'-'+M+'-'+d +" "+ h + ":" + m + ":" + s ; }, var dt = getFormateDate(new Date()); console.log(dt) ~~~ 2. Math * 获取随机数 Math.random() //作用:随时改变,清除缓存(链接后加随机数参数)(小数点位置不能保证) 3. 数组API * forEach 遍历所有元素 * every 判断所有元素是否符合条件 * some 判断是否至少一个元素符合条件 * sort 排序 (对象数组按属性排序) * map 对元素重新组装,生成新数组 * filter过滤符合条件的元素 * slice(start,end);//start必选 -1指最后一个元素,-2值倒数第二个 ~~~ var arr = [0,1,2]; console.log(arr.slice(0,10));// [0,1,2]; console.log(arr.slice(1)) //[1,2] console.log(arr.slice(-2,-1)) //[1] ~~~ * splice:数组中添加/删除元素:arrayObject.splice(index,howmany,item1,.....,itemX)。index是必选的,规定添加/删除项目的位置。howmany必须项,表示删除项目的个数,如果为0表示不删除元素。splice()可删除从index开始的howmany个元素,并可以用item元素替代删除的元素。item可选参数,表示新添加的项。 ~~~ var arr = [1,2,3]; arr.splice(1,2,1,1); console.log(arr)//111 ~~~ * split: 将字符串切成数组 ~~~ var arr = [1,2,3]; arr.forEach(function(item,index){ }) ~~~ ~~~ var arr = [1,2,3]; var result = arr.every(function(item,index){ //用来判断所有的数组元素,都满足一个条件 if(item<4){ return true } }) console.log(result) //true ~~~ ~~~ var arr = [1,2,3]; var result = arr.some(function(item,index){ //用来判断所有的数组元素,只要有一个满足条件即可 if(item<4){ return true } }) console.log(result) //true ~~~ ~~~ var arr = [1,4,2,3,5]; var arr2 = arr.sort(function(a,b){ //从小到大 return a - b //从大到小 //return b-a }) var arr = [{a:2,b:2},{a:1,b:1}] var arr2 = arr.sort(function(a,b){ //从小到大 return a.a - b.a }) console.log(arr2); ~~~ ~~~ var arr = [1,4,2,3,5]; var arr2 = arr.map(function(item,index){ //将元素重新组装并返回 return '<b>'+item+'</b>' }) console.log(arr2); ~~~ ~~~ var arr = [1,4,2,3,5]; var arr2 = arr.filter(function(item,index){ //通过某一个条件过滤数组 if(item >= 3){ return true } }) console.log(arr2) ~~~ 4. 对象API * for in ~~~ var obj = {x:1,y:2}; var key for(key in obj){ //注意,hasOwnProperty if(obj.hasOwnProperty(key)){ console.log(key,obj[key]) } } ~~~ ### 解答 1. 获取 2017-06-10格式的日期 ~~~ getFormateDate(date){ if(!date){ date = new Date()} var y = date.getFullYear(); var M = date.getMonth()+1; var d = date.getDate(); var h = date.getHours(); var m = date.getMinutes(); var s = date.getSeconds(); M = M>9?M:'0'+M; d = d>9?d:'0'+d; h = h>9?h:'0'+h; m = m>9?m:'0'+m; s = s>9?s:'0'+s; return y+'-'+M+'-'+d +" "+ h + ":" + m + ":" + s ; }, var dt = getFormateDate(new Date()); console.log(dt) ~~~ 2. 获取随机数,要求是长度一致的字符串格式 ~~~ var random = Math.random(); var random = random+"0000000000"//后面加上10个0 var random = random.slice(0,10) ~~~ 3. 写一个能遍历对象和数组的通用forEach函数 ~~~ function forEach(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 = [11,22,33]; forEach(arr,function(index,item){ console.log(index,item) }) var obj = {x:100,y:2000}; forEach(obj,function(key,value){ console.log(key,value) }) ~~~