变量和计算
js中使用typeof能得到哪些类型?
总共6种(如果不包含es6里面的Symbol类型)
typeof undefined //underfined
typeof 'abc' //string
typeof 123 //number
typeof true //boolean
typeof {} //object
typeof [] //object
typeof null //object
typeof console.log //function
说明:typeof只能区分值类型和函数(引用类型),对于引用数据类型就直接被当作object
强制类型转换
可能引起强制类型转换的操作
- 字符串拼接
- ==运算符
- if语句
- 逻辑运算
100+'10' //10010
100=='100' //true
0=='' //true
null==underfined //true
var a=true;
var b=100;
var c='';
if(a/b/c){}
//逻辑运算
console.log(10&&0);//0
console.log(''||'abc');//'abc'
console.log(!window.abc);//true
&&:当数值参与逻辑与运算时,结果为true,那么会返回的会是第二个为真的值;如果结果为false,返回的会是第一个为假的值。
||:当数值参与逻辑或运算时,结果为true,会返回第一个为真的值;如果结果为false,会返回第二个为假的值;
补充:逻辑与的优先级是高于逻辑或的;
何时使用===何时使用==?
==有类型转换,===没有类型转换
if(obj.a===null||obj.a===underfined){}
等效于:
if(obj.a==null)
因为:null==underfined
除了上述情况用==简写之外,其他全部都用===
js中有哪些内置函数(数据封装类对象)
- Object
- Array
- Boolean
- Number
- String
- Function
- Date
- RegExp
- Error
js变量按照存储方式区分为哪些类型,并描述其特点
值类型和引用类型
如何理解json
Json只不过是一个js对象
JSON.stringify({a:10,b:20})
JSON.parse('{"a":10,"b":20}')
``
##实现数组随机排序
# 原型和原型链
## 构造函数
> 规则:函数名大写的函数,一般就是构造函数
```js
function Foo(name,age){
this.name=name;
this.age=age;
// return this; 此行可以省略
}
var f=new Foo('zhangsan',20);
console.log(f instanceof Foo );//true
构造函数-扩展
var a={}其实是var a=new Object()的语法糖
var a=[]其实是var a=new Array()的语法糖
function Foo(){}其实是var Foo=new Function()
使用instanceof判断一个引用类型是否是一个变量的构造函数的方法
例如: f instance Foo的判断逻辑
f的__proto__一层一层往上,能否对应到Foo.prototype
原型规则
- 所有的引用类型(数组,对象,函数),都具有对象特性,即可以自由扩展属性(除了“null”以外)
- 所有的引用类型(数组,对象,函数),都有一个proto属性(隐式原型),属性值是一个普通的对象
- 所有的函数,都有一个prototype属性(显式原型),属性值也是一个普通的对象
- 所有的引用类型(数组,对象,函数),proto属性值指向它的构造函数的"prototype"属性
- 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找
- 所有引用类型,都有constructor属性,指向它的构造函数(但是实际上,constructor属性是引用类型数据本身没有的,都是其原型上面才有constructor属性)
- 原型其实是一个指针对象,指向一个(初始时候)公用的空对象
var obj={};
obj.a=100;
function fn(){}
console.log(obj.__proto__);
console.log(fn.prototype);
console.log(obj.__proto__===Object.prototype);//true
说明:注意此时obj没有prototype属性值,因为不是函数;至于最后的true,是因为{}是语法糖,对应的是new Object(),所以Object是个构造函数,所以有prototype属性值。
补充案例:
function Animal(age){
this.age=age;
}
var a=new Animal(12);
console.log(a.constructor===Animal)//true
console.log(a.__proto__===Animal.prototype) //true
console.log(Animal.constructor===Function)//true
var arr=[];
console.log(arr.constructor) //ƒ Array() { [native code] }
//arr.__proto__===Array.prototype(true) 原型上面才有constructor属性
console.log(arr.__proto__.constructor===arr.constructor);//true
function Foo(name,age){
this.name=name;
}
Foo.prototype.alertName=function(){
alert(this.name);
}
var f=new Foo('zhangsan');
f.printName=function(){
console.log(this.name);
}
f.printName();
f.alertName();
说明:f.alertName();本身f对象没有这个属性,就会去查询隐式原型,即构造函数上面的prototype中去查询。
补充:不论是对象本身属性还是从原型上面继承的属性,this都指向该对象本身。
循环对象自身的属性
for (const item in f) {
if (f.hasOwnProperty(item)) {
console.log(item);
}
}
说明:hasOwnProperty是过滤来自原型的属性,如果去掉判断就输出name printName alertName;加上判断输出name printName
原型链
function Foo(name,age){
this.name=name;
}
Foo.prototype.alertName=function(){
alert(this.name);
}
var f=new Foo('zhangsan');
f.printName=function(){
console.log(this.name);
}
f.toString();//要去f.__proto__.__proto__
说明:因为f本身没有这个属性,会去隐式原型查找,但是此时其隐式原型上面也没有,其隐式原型也是一个Object,也有构造函数,所以其隐式原型会继续往上去隐式原型的隐式原型上面找。
f.__proto__.__proto__对应的就是Object.prototype。此时Object是有toString的,如果还没有就直接去null上找。
准确判断一个变量是数组类型
typeof无法再引用类型之间做准确区分
arr instanceof Array
写一个原型链继承的例子
描述new一个对象的过程
function Foo(name,age){
this.name=name;
this.age=age;
// return this; 此行可以省略
}
var f=new Foo('zhangsan',20);
说明:
创建一个新对象
this指向这个新对象
执行代码,即对this赋值
返回this
作用域和闭包
函数声明和函数表达式
函数声明:
function Foo(name){}
函数表达式:
var Foo=function(name){}
说明this几种不同使用场景
this要在执行时确认,定义时无法确认
var a={
name:'A',
fn:function(){
console.log(this.name);
}
}
a.fn()//this===a
a.fn.call({name:'B'})//this==={name:'B'}
var fn1=a.fn;
fn1()//this===window
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call apply bind
当函数调用call和apply时,都会执行函数调用
function fn(name){
console.log(this);
}
fn();//window
fn.call({x:10},"san");//{x: 10}
fn.apply({x:100},["san"]);//{x: 10}
var fn1=function (name){
console.log(this);
}.bind({y:2000})
fn1("三")//{y: 2000}
闭包
函数作为返回值或函数作为参数来传递
function F(){
var a=100;
return function(){
console.log(a);
}
}
var f=F();
var a=200;
f();
一个关于setTimeout的笔试题
console.log(1);
setTimeout(()=>{
console.log(2);
},0)
console.log(3);
setTimeout(()=>{
console.log(4);
},1000)
console.log(5);
输出:1 3 5 2 4
继承
原型链继承
缺点:无法传递new对象的时候参数
基本案例:
function Person(name,age){
this.name=name;
this.age=age;
this.run=function(){
console.log(this.name,this.age);
}
}
Person.prototype.work=function(){
console.log("work");
}
function Student(name,age){
}
Student.prototype=new Person();
var s=new Student("qiang",12);
s.run();//undefined undefined
s.work();//work
对象冒充继承
无法使用静态方法和原型上面的方法
基本案例:
function Person(name,age){
this.name=name;
this.age=age;
this.run=function(){
console.log(this.name,this.age);
}
}
function Student(name,age){
Person.call(this,name,age);
}
//Student.prototype=new Person();
var s=new Student("qiang",12);
s.run(); //qiang 12
s.work();//报错
综合案例(原型链继承和对象冒充继承一起用)
function Person(name,age){
this.name=name;
this.age=age;
this.run=function(){
console.log(this.name,this.age);
}
}
Person.prototype.work=function(){
console.log("work");
}
function Student(name,age){
Person.call(this,name,age);
}
Student.prototype=new Person();
var s=new Student("qiang",12);
s.run(); //qiang 12
s.work();//work
日期
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)
dt.getSeconds();//秒(0-59)
Math
Math.random()//获取随机数
数组api
forEach //遍历所有元素
every //判断所有元素是否都符合条件
some //判断是否有至少一个元素符合条件
sort //排序
map //对元素重新组装,生成新数组
filter //过滤符合条件的元素
案例:
var arr=[1,2,3];
arr.forEach(function(item,index){
//item就是元素值,index是索引
console.log(index,item);
})
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);//false
var arr=[1,4,2,3,5];
var result=arr.sort(function(a,b){
return a-b;//从小到大排序
// return b-a; 从大到小排序
})
var arr=[1,4,2,3,5];
var result=arr.map(function(item,index){
return item+2;
})
console.log(result);//[3,6,4,5,7]
var arr=[1,4,2,3,5];
var result=arr.filter(function(item,index,arr){
return item>3;
})d
console.log(result);//[4,5]
获取2017-06-10格式的日期
var dt=new Date();
var formatDate=formatDate(dt);
console.log(formatDate);
function formatDate(dt){
if(!dt){
dt=new Date()
}
var year=dt.getFullYear();
var month=dt.getMonth()+1;
var date=dt.getDate();
if(month<10){
month='0'+month;
}
if(date<10){
date='0'+date;
}
return year+'_'+month+'_'+date;
}
获取随机数,要求是长度一致的字符串格式
var random=Math.random();
var random=random+'0000000000';
var random=random.slice(0,10);
console.log(random);
写一个能遍历对象和数组的通用的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]);
}
}
}
DOM
JS-Web-API
获取dom节点
var div1=document.getElementById('div1');//元素
var divList=document.getElementsByTagName('div');//集合
var containerList=document.getElementsByClassName('.container');//集合
var pList=document.querySelectorAll('p');//集合
新增节点
var div1=document.getElementById('div1');//元素
//添加新节点
var p1=document.createElement('p');
p1.innerHTML='this is p1';
div1.appendChild(p1);//添加新建的元素
//移动已有节点,这是移动
var p2=document.getElementById('p2');
div1.appendChild(p2);
获取父元素和子元素
var div1=document.getElementById('div1');//元素
var parent=div1.parentElement
var child=div1.childNodes
//删除该子元素
div1.removeChild(child[0]);
property(针对js对象的属性)
var pList=document.querySelectorAll('p');//集合
var p=pList[0];
console.log(p.style.width);//获取样式
p.style.width='100px';//修改样式
console.log(p.className);//获取class
p.className='p1';//修改class
//获取nodeName和nodeType
//此外还有nodevalue
console.log(p.nodeName);
console.log(p.nodeType);
Attribute(针对html标签的属性)
var pList=document.querySelectorAll('p');//集合
var p=pList[0];
p.getAttribute('data-name');
p.setAttribute('data-name','imooc');
p.getAttribute('style');
p.setAttribute('style','font-size:30px');
BOM
navigator&screen
var ua=navigator.userAgent;
var isChrome=ua.indexOf('Chrome');
console.log(isChrome);
console.log(screen.width,screen.height);
location&history
console.log(location.href);//整个url
console.log(location.protocol);//协议
console.log(location.host);//域名
console.log(location.pathname);//路径
console.log(location.search);//?后的参数
console.log(location.hash);//#后面的哈希
//history
history.back()
history.forward()
如何检测浏览器类型
简化版本:
var ua=navigator.userAgent;
var isChrome=ua.indexOf('Chrome');
console.log(isChrome);
事件
标准事件绑定
var btn=document.getElementById('btn1');
btn.addEventListener('click',function(event){
console.log('clicked');
})
通用事件绑定
function bindEvent(elem,type,fn) {
elem.addEventListener(type,fn);
}
var a=document.getElementById('link1');
bindEvent(a,'click',function(e){
//因为a标签有默认行为
e.preventDefault();//阻止默认事件
alert('clicked');
})
事件冒泡
<body>
<div id="div1">
<p>激活</p>
<p>取消</p>
<p>取消</p>
<p>取消</p>
</div>
</body>
题目:点击对应条目弹出对应的弹窗信息
如果简单思考,肯定是挨个绑定,但是这样就太麻烦,如果条目很多,几乎不可能完成,事件冒泡可以解决问题。
//上面通用绑定的方法
var p1=document.getElementById("p1");
var body=document.body;
bindEvent(p1,'click',function(e){
e.stopPropagation();//阻止冒泡
alert("激活");
})
bindEvent(body,'click',function(e){
alert("取消");
})
代理(冒泡的应用)
var div1=document.getElementById('div1');
div1.addEventListener('click',function(e){
var target=e.target;
if(target.nodeName==='P'){
console.log(target.innerHTML);
}
})
ajax
XMLHttpRequest
var xhr=new XMLHttpRequest()
xhr.open("GET","/api",false);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
alert(xhr.responseText);
}
}
}
xhr.send(null);
状态码
0 (未初始化) 还没有调用send()方法
1 (载入)已经调用send()方法,正在发送请求
2 (载入完成)send() 方法执行完毕,已经收到全部相应内容
3 (交互)正在解析响应的内容
4 (完成)相应内容解析完毕,可以在客户端使用了
----------
2xx 表示成功处理请求。如200
3xx 需要重定向,浏览器直接跳转
4xx 客户端请求错误,如404
5xx 服务器错误
跨域
浏览器有同源策略,不允许访问其他域的接口
协议、域名、端口、有一个不同就算跨域
可以跨域的三个标签:
<img src=xxx>
<link href=xxx>
<script src=xxx>
注意事项:
所有的跨域请求都必须经过信息提供方允许
JSONP
<script>
window.callback=function(data){
//这是跨域得到的信息
console.log(data);
}
</script>
<script src="http://coding.com/api.js"></script>
说明:api.js中内容是
callback({x:100,y:200})
src引入这个js文件,则相当于执行callback,那么上面的window.callback自然就会得到api.js中的数据。
补充:服务器端设备http header也可以解决跨域问题
cookie
存储量小,只能4KB
所有http请求都带着,会影响获取资源的效率
sessionStorage和localStorage
html5专门为存储设计的,最大容量5m
sessionStorage会再页面会话时候清理
safari隐藏模式下,localStorage可能出错
网友评论