## 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)
})
~~~
- 空白目录
- 双樾
- JS基础知识
- JS-WEB-API
- 开发环境
- 运行环境
- ES6
- 原型
- 异步
- 虚拟dom
- mvvm
- 组件化和React
- hybrid
- 其他
- 补充
- 技巧
- 快乐动起来呀
- css
- 掘金小册子
- js基础知识
- ES6知识点
- JS异步
- JS进阶知识
- 思考题
- DevTools Tips
- 浏览器基础知识
- 浏览器缓存机制0
- 浏览器渲染原理
- 安全防范知识点0
- 从V8中看JS性能优化0
- 性能优化琐碎事
- Webpack性能优化0
- 实现小型打包工具0
- React和Vue
- Vue生命周期
- vue基础知识点
- Vue响应式
- vue高级
- React基础
- Vue.js技术解密
- 准备工作
- 数据驱动
- new Vue()
- vue实例挂载
- 组件化
- 深入响应式原理
- 编译
- 扩展
- Vue Router
- Vuex