//JS的基本数据类型
//Undefined、Null、Boolean、Number、String 新增:Symbol
//JS有哪些内置对象?
//Object 是 JavaScript 中所有对象的父对象
//数据封装类对象:Object、Array、Boolean、Number 和 String
//其他对象:Function、Arguments、Math、Date、RegExp、Error
//JS中使用typeof能得到的哪些类型?(考点:JS变量类型)
//typeof undefinded //undefined
//声明变量但是未初始化值时
var obj;
console.log(typeof(obj))
//typeof null // object
var obj = null
console.log("typeof:"+typeof(obj))
//typeof'abc' // string
var obj = "123"
console.log("typeof得到:"+typeof(obj))
//typeof 123 // number
var obj = 1
console.log("typeof得到:"+typeof(obj))
//typeof [] // object
var obj = [0,1,2]
console.log("typeof得到t:"+typeof(obj))
//typeof {} // object
var obj = {}
console.log("typeof得到:"+typeof(obj))
//typeof true //boolean
var obj = true
console.log("typeof得到:"+typeof(obj))
//typeof b // b 没有声明,但是还会显示 undefined
console.log("typeof得到:"+typeof(b))
//先定义一个变量/json串 obj
var obj = {"a":"0","b":"1"};
if (obj.a == null) {
// 这里相当于 obj.a === null || obj.a ===undefinded, 简写形式
// 这里jquery 源码中推荐的写法
console.log("数据为空")
} else {
console.log("当前获取的值:" + obj.a)
}
//或者定义一个数组 arr
var arr = ["1","2","3"];
//遍历数组元素
for(var i = 0;i<arr.length;i++){
console.log(arr[i])
}
//Javascript创建对象的几种方式?
//1、对象字面量的方式
var a = {}
//2、通过构造函数方式创建。
var obj = new Object();
console.log("构造函数:"+obj)
console.log("解析object"+JSON.stringify(obj))
//3、通过Object.create()方式创建。
var obj = Object.create(Object.prototype);
console.log("通过Object.create()方式创建:"+obj)
//翻转一个字符串
//可以先将字符串转成一个数组,然后用数组的reverse()+join()方法。
let str="hello word";
let fz=[...str].reverse().join("");
console.log("翻转:" + fz)
let fzoption = "Aurora"
let option=[...fzoption].reverse().join("")
console.log("复习翻转一个字符串:" + option)
//描述new一个对象的过程
//1、创建一个新对象
let parent = function(name,nl){
//2、this指向这个对象
let that = this
//3、执行代码,即对this赋值
that.name = "刘";
that.nl = 20;
//4、隐式返回this
return that;
console.log(parent)
}
//JS按存储方式区分变量类型
// 值类型
var a = 10
var b = a
a = 11
console.log("值类型:"+b) // 10
// 引用类型
var obj1 = {x : 100}
var obj2 = obj1
obj1.x = 200
console.log("引用类型:"+JSON.stringify(obj2)) // 200
//如何判断一个变量是对象还是数组?
//1、instanceof方法
//instanceof运算符是用来测试一个对象是否在其原型链原型构造函数的属性
var arrdx = [1,2,3];
console.log("对象类型:" + arrdx instanceof Object)
var arr1 = ["a","b"]
console.log("数组类型:" + arr1 instanceof Array)
//2、constructor方法 constructor属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数
var arr2 = [];
console.log("constructor 数组"+arr2.constructor == Array)
var arr3 = [];
console.log(arr2.constructor == Object)
//3、最简单的方法,这种写法兼容性最好使用Object.prototype.toString.call()
// var value = [0,1,2,3]
// setTimeout(function (){
// isobjorarr(value);
// },300)
// function isobjorarr(value){
// if(Object.prototype.toString.call(value) === "[Object Array]"){
// console.log("value是数组")
// } else if(Object.protypeof.toString.call(value) === '[Object Object]'){
// console.log("value是对象")
// } else {
// console.log("value既不是对象,也不是数组")
// }
// }
//4、ES5新增方法isArray() 千万不能使用typeof来判断对象和数组,因为这两种类型都会返回"object"。
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false
//如何对一个数组去重?
//1、Set结构去重(ES6用法)。
//ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
var arr = [1,1,2,2,3,3]
var qc = [...new Set(arr)]
console.log("数组去重" + qc)
//作用域和闭包
//var、let、const之间的区别
//var声明变量可以重复声明,而let不可以重复声明
//var是不受限于块级的,而let是受限于块级
//var会与window相映射(会挂一个属性),而let不与window相映射
//var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错
//const声明之后必须赋值,否则会报错
//const定义不可变的量,改变了就会报错
//const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错
//说明This几种不同的使用场景
//1、作为构造函数执行
//2、作为对象属性执行
//3、作为普通函数执行
//4、call apply bind
//作用域
//块级作用域
if(true){
var names = 'zhangsan'
}
console.log(names)
//函数和全局作用域
var qj1 = 200;
function fn (){
var qj1 = 300;
console.log('fn', qj1)
}
//用JS创建10 个<a>标签,点击的时候弹出来对应的序号?
// var jsa ;
// for(jsa = 0;jsa<10;jsa++){
// (function (jsa){
// var abq = document.createElement('a')
// abq.innerHTML= jsa + '<br>'
// jsa.addEventListener('click',function (e){
// e.preventDefault()
// alert(jsa)
// })
// document.body.appendChild(abq)
// })(jsa)
// }
//获取随机数,要求是长度一致的字符串格式
var random = Math.random()
var random = random + '0000000000'
console.log(random)
var random = random.slice(0, 10)
console.log(random)
//复习
var fxrandom = Math.random()
console.log(fxrandom)
//谈谈你对作用域链的理解
//1.作用域链的作用是指在执行的环境里有权访问的变量和函数是有序的,作用域链只能向上访问,作用域链的变量访问到windows对象即被终止,作用域链向下访问不被允许
//2.简单来说,作用域就是变量与函数的可访问范围,即作用域控制着变量域函数的可见性和生命周期
//3.一般情况下,变量取值到创建这个变量的函数的作用域中取值,但是在当前作用域中没有查询到这个值,就会向上级作用域去查,直到查到全局作用域,在查找过程中形成的链条就叫作用域链
var zyya = 100;
function zyy(){
var zyyb = 200;
//当前作用域没有定于的变量,即自由变量
console.log("zyya:"+zyya);
console.log("zyyb:"+zyyb);
}
zyy()
console.log("去父级作用域链找zyya自由变量:"+zyya)
//闭包
//闭包就是能够读取其他函数内部变量的函数;
//闭包是指有权访问另一个函数作用域中变量的函数,最常见的是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用域链
function F1(){
var f1a = 100
return function(){
console.log(f1a)
}
}
var f1 = F1();
var f1b = 200
f1();
function F2(fn){
var f1a = 200
fn()
}
F2(f1)
//闭包的特性:函数内嵌套函数,外部函数定义变量,内部函数调用变量,参数和变量不会被垃圾回收机制回收(谁调用谁改变)
//闭包的理解:使用闭包是为了设计私有的方法和变量,优点:避免全局变量的污染,缺点:闭包会常驻内存,增大内存使用量,使用不当会造成内存泄漏 - 在Js中,函数即闭包
//闭包最大的用处有两个:读取函数内部的变量,让这些变量始终保持在内存中 - 封装对象的私有属性和私有方法 好处:能够实现封装和缓存 坏处:消耗内存,使用不当会造成内存泄漏。
//使用闭包的注意点:内存消耗大,不能滥用闭包,再退出函数之前,将不使用的局部变量全部删除
//闭包的使用场景:函数作为返回值,函数作为参数传递
//实际开发中的闭包应用:用于封装变量 收敛权限
// 闭包实际应用中主要用于封装变量 收敛权限
function isFirstLoad() {
var _list = []
return function (id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = new isFirstLoad()
firstLoad(10) //true
firstLoad(10) //false
firstLoad(30) //true
//原型和原型链
//JavaScript原型,原型链 ? 有什么特点?
//每个对象都会在其内部初始化一个属性,就是prototype原型
//关系:instance.constructor.prototype = instance._proto_
//原型和原型链特点:
//所有的引用类型(数组,对象,函数)都具有对象的特性,即自由扩展属性(除 null),都有一个_proto_隐式原型属性,属性值是一个普通对象,指向它构造的prototype属性值
//所有的函数,都有一个Protype(显示原型)的属性,也是一个普通对象
//当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_即构造它函数的prototype中寻找
//循环对象自身的属性
//原型链
// var item
// for (item in f) {
// // 高级浏览器已经在 for in 中屏蔽了来自原型的属性
// // 但是这里建议大家还是加上这个判断,保证程序的健壮性
// if (f.hasOwnProperty(item)) {
// console.log(item)
// }
// }
// f.toString() //到f._proto_._proto_ 中去找
//异步和单线程:
//同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程。
//异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。
//相同的地方:都属于交互方式,都是发送请求。
//不同的地方:一个需要等待,一个不需要等待。
//异步编程的实现方式?
//1、回调函数
//优点:简单、容易理解
//缺点:不利于维护,代码耦合高
//2、事件监听(采用时间驱动模式,取决于某个事件是否发生):
//优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数
//缺点:事件驱动型,流程不够清晰
//3、发布/订阅(观察者模式)
//类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者
//4、Promise对象
//优点:可以利用then方法,进行链式写法;可以书写错误时的回调函数;
//缺点:编写和理解,相对比较难
//5、Generator函数
//优点:函数体内外的数据交换、错误处理机制
//缺点:流程管理不方便
//6、async函数
//优点:内置执行器、更好的语义、更广的适用性、返回的是Promise、结构清晰。
//缺点:错误处理机制
//定时器的执行顺序或机制
//前段使用异步的场景
//1、定时任务:setTimeout,setInverval
//2、网络请求:ajax请求,动态<img>加载
//3、事件绑定
//数组和对象API
//map与forEach的区别?
//1、forEach方法,是最基本的方法,就是遍历与循环,默认有3个传参:分别是遍历的数组内容item、数组索引index、和当前遍历数组Array
//2、map方法,基本用法与forEach一致,但是不同的,它会返回一个新的数组,所以在callback需要有return值,如果没有,会返回undefined
//写一个能遍历对象和数组的通用forEach函数
function forEach(obj3,fn3){
var key
//判断类型
if(obj3 instanceof Array){
obj3.forEach(function(item,index){
fn3(index,item)
})
} else {
for(key in obj3){
fn3(key,obj3[key])
}
}
}
//map: 遍历数组,返回回调返回值组成的新数组
//forEach: 无法break,可以用try/catch中throw new Error来停止
//filter: 过滤
//some: 有一项返回true,则整体为true
//every: 有一项返回false,则整体为false
//join: 通过指定连接符生成字符串
//push / pop: 末尾推入和弹出,改变原数组, 返回推入/弹出项【有误】
//unshift / shift: 头部推入和弹出,改变原数组,返回操作项【有误】
//sort(fn) / reverse: 排序与反转,改变原数组
//concat: 连接数组,不影响原数组, 浅拷贝
//slice(start, end): 返回截断后的新数组,不改变原数组
//splice(start, number, value...): 返回删除元素组成的数组,value 为插入项,改变原数组
//indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标
//reduce / reduceRight(fn(prev, cur), defaultPrev): 两两执行,prev 为上次化简函数的return值,cur 为当前值(从第二项开始)
//日期和随机数
function getdate(){
var dt = new Date();
var hm = dt.getTime();
console.log(dt.getFullYear())
var nd = dt.getFullYear();
var yf = dt.getMonth() + 1;
var rq = dt.getDate();
var xs = dt.getHours();
var fzs = dt.getMinutes();
var ms = dt.getSeconds();
if (yf < 10) yf = "0" + yf;
if (rq < 10) rq = "0" + rq;
return nd + "-" + yf + "-" + rq;
}
console.log(getdate())
//如何检测浏览器的类型
//可以通过检测navigator.userAgent 在通过不通浏览器的不通来检测
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(ua)
//拆解url的各部分
//使用location里面的location.href location.protocol location.pathname location.search location.hash来获取各种参数
console.log("地址:"+location.href)
console.log("域名:"+location.host) //域名
console.log("协议:"+location.protocol)
console.log("路径:"+location.pathname) //路径
console.log(location.search) // 参数
console.log(location.hash)
//XML和JSON的区别?
//数据体积方面
//JSON相对于XML来讲,数据的体积小,传递的速度更快些。
//数据交互方面
//JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互
//数据描述方面
//JSON对数据的描述性比XML较差
//传输速度方面
//JSON的速度要远远快于XML
//get和post的区别
//1、get和post在HTTP中都代表着请求数据,其中get请求相对来说更简单、快速,效率高些
//2、get相对post安全性低
//3、get有缓存,post没有
//4、get体积小,post可以无限大
//5、get的url参数可见,post不可见
//6、get只接受ASCII字符的参数数据类型,post没有限制
//7、get请求参数会保留历史记录,post中参数不会保留
//8、get会被浏览器主动catch,post不会,需要手动设置
//9、get在浏览器回退时无害,post会再次提交请求
//post一般用于修改服务器上的资源,对所发送的信息没有限制。比如
//1、无法使用缓存文件(更新服务器上的文件或数据库)
//2、向服务器发送大量数据(POST 没有数据量限制)
//3、发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
//谈谈你对ES6的理解
//新增模板字符串(为JavaScript提供了简单的字符串插值功能)
//箭头函数
//for-of(用来遍历数据—例如数组中的值。)
//arguments对象可被不定参数和默认参数完美代替。
//ES6将promise对象纳入规范,提供了原生的Promise对象。
//增加了let和const命令,用来声明变量。
//增加了块级作用域。
//let命令实际上就增加了块级作用域。
//还有就是引入module模块的概念
//forEach、for in、for of三者区别
//forEach更多的用来遍历数
//for in一般常用来遍历对象或json
//for of数组对象都可以遍历,遍历对象需要通过和Object.keys()
//for in循环出的是key,for of循环出的是value
//Set、Map的区别
//应用场景Set用于数据重组,Map用于数据储存
//Set:
//1,成员不能重复
//2,只有键值没有键名,类似数组
//3,可以遍历,方法有add, delete,has
//Map:
//1,本质上是健值对的集合,类似集合
//2,可以遍历,可以跟各种数据格式转换
//浅拷贝
let nla = {
age:23
}
let nlb = Object.assign({},nla)
nla.age = 24
console.log(nlb.age)
//深拷贝,这个问题通常可以通过JSON.parse(JSON.stringify(object)) 来解决
let bb = {
af:1,
jobs:{
first:'2'
}
}
let rr = JSON.parse(JSON.stringify(bb))
console.log(rr.jobs.first)
//JavaScript性能优化
//1、尽可能把 <script> 标签放在 body 之后,避免 JS 的执行卡住 DOM 的渲染,最大程度保证页面尽快地展示出来
//2、尽可能合并 JS 代码:提取公共方法,进行面向对象设计等……
//3、CSS 能做的事情,尽量不用 JS 来做,毕竟 JS 的解析执行比较粗暴,而 CSS 效率更高。
//4、尽可能逐条操作 DOM,并预定好 CSs 样式,从而减少 reflow 或者 repaint 的次数。
//5、尽可能少地创建 DOM,而是在 HTML 和 CSS 中使用 display: none 来隐藏,按需显示。
//6、压缩文件大小,减少资源下载负担。
//JavaScript几条基本规范
//1、不要在同一行声明多个变量
//2、请使用===/!==来比较true/false或者数值
//3、使用对象字面量替代new Array这种形式
//4、不要使用全局变量
//5、Switch语句必须带有default分支
//6、函数不应该有时候有返回值,有时候没有返回值
//7、For循环必须使用大括号
//8、IF语句必须使用大括号
//9、for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污染
//手写一个promise
var promise = new Promise((resolve,reject) =>{
if(success){
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value){
//success
},function (value){
//error
})
//promise 的使用场景:ajax请求,回调函数、复杂操作判断
//promise是ES6为了异步编程所诞生的
//异步操作解决方案 promise、Generator、定时器
//举例一个冒泡排序
var arrtest = [0,2,1,6,3]
function px(arrtest){
for(var q = 0; q < arrtest.length;q++){
for(var e =0;e<arrtest.length -q -1;e++){
if(arrtest[e+1]<arrtest[e]){
var temp;
temp=arrtest[e];
arrtest[e] = arrtest[e+1]
arrtest[e+1] = temp
}
}
}
return arrtest;
}
console.log(px(arrtest))
//写一个能遍历对象和数组的通用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])
}
}
}
//使用jquery写一个简单的Ajax请求
// $.ajax({
// url:'/api',
// type:'post',
// data:{},
// dataType:'json',
// success:function(res){
// console.log(res)
// }
// })
//Ajax工作原理
var xhr = new XMLHttpRequest();
xhr.open('get','请求地址');
var ee =[1,0,0,2,2,3,2,3,5,4,8,9]
var ee=[...new Set(ee)]
console.log(ee)
console