typeof()
- 值类型 "underfind" "string" "number" "boolean" "symbol"
- 函数 "function"
- 引用类型 "Object" 数组 [] 对象 {} 注意:null 指向空地址 特殊引用类型
字符串拼接
数字相加 = 数字
字符串相加 = 拼接
什么时候用 === 什么时候用==
null == underfined
== 运算符会类型转换
判断是否等于null或者underfined之外,其他一律用 ===
if else 也会变量转换
&& || !
class函数继承
class Test{
constructor(name){
this.name = name
}
eat(){
console.log(`${this.name} eat something`)
}
}
class Student extends Test{
constructor(name, number){
super(name);//执行父类的构造函数
this.number = number;
}
sayHi(){
console.log(`姓名${this.name} 学号${this.number}`)
}
}
const sunny = new Student('苏珊娜','21')
console.log(sunny.name);
手写jquery
class jQuery{
constructor(selector){
const result = document.querySelectorAll(selector);
const length = result.length;
for(let i = 0; i < length;i++){
this[i] = result[i]
}
this.length = length
this.selector = selector
}
get(index){
return this[index]
}
each(fn){
for(let i = 0;i < this.length;i++){
const item = this[i];
fn(item);
}
}
on(type, fn){
return this.each(item =>{
item.addEventListener(type, fn, false)
})
}
}
const $p = new jQuery('p');
$p.get(1);
$p.each((item) => console.log(item.nodeName));
$p.on('click',() => console.log('clicked'));
作用域
全局作用域
函数作用域
块级作用域(ES6新增) let const 外部不能使用
闭包
- 缺点:会造成内存泄露
- 优点:模块化开发防止全局变量 属性私有化
function test() {
var num = [];
for(var i = 0;i < 10; i++){
(function(j){
num[i] = function(){
console.log(j);
}
}(i))//闭包解决办法 立即执行函数
}
return num;
}
var gettest = test();
for(var j = 0;j < 10; j++){
gettest[j]();
}
function createCache(){
const data = {};
return{
set:function(key, val){
data[key] = val;
},
get: function(key){
return data[key];
}
}
}
const item = createCache();
item.set('a',800);
console.log(item.get('a'));//800
1.函数作为参数
function print(fn){
const a = 100;
fn();
}
const a = 200;
function fn(){
console.log(a);
}
console.log(print(fn))//200
//所有自由变量的查找是在函数定义的地方,不是函数执行的地方,向上级作用于查找不是执行的地方
2.函数作为返回值
function create(){
const a = 100;
return function(){
console.log(a)
}
}
const a = 200;
const fn = create();
fn();//100
this
this的作用
1.当做函数调用 2.当做构造函数调用 3.当做属性值调用
this取什么值是在函数执行时确认的
const zhansan = {
name:'张三',
sanHi(){
console.log(this);
},
wait(){
setTimeout(function(){
console.log(this);//指向window
})
// setTimeout(() => {
// console.log(this);
// },); //箭头函数指向他的上级作用域
}
}
this的不同应用场景
1.当做普通函数被调用
2.通过call apply bind 改变this指向
3.通过对象调用 返回对象本身
4.在class的方法中调用 指向他的实例
5.箭头函数会找他的上级作用域
手写bind()方法
Function.prototype.bind1 = function (){
const list = Array.prototype.slice.call(arguments);
const t = list.shift();
const self = this;//this就是fn1
return function(){
return self.apply(t, list)
}
}
function fn1(a,b,c){
console.log('this',this);
console.log(a,b,c);
return 'this is fn1'
}
const fn2 = fn1.bind({x:100},10,20,30);
console.log(fn2())
异步和单线程
同步和异步的区别是什么?
基于JS是单线程语言
异步不会阻塞代码执行
同步会阻塞代码的执行
前端异步的使用场景有哪些?
1.网络请求,如ajax图片加载
2.定时任务,如setTimeout
异步
console.log(100);
setTimeout(() => {
console.log(888);
}, 1000);
console.log(400);
同步
console.log(100);
alert(200);// 必须等它执行了才会执行下面
console.log(400);
预编译
1.函数声明整体提升
2.变量 声明提升
3.没有声明就使用的变量为全局变量 全局变量为window所有
2.创建AO
1.形参和变量声明名作为AO对象属性名 2.值为undefined 3.形参实参值统一4.找函数声明名为函数体
立即执行函数
1.只有表达式才能被执行 ()执行符 函数表达式立即执行会失去函数索引
2.函数声明(加 + - ! ())可以变成表达式
var x = 1;
if (function f() { }) {//typeof()是唯一可以返回没有定义的变量
x += typeof f
}//'1undefined'
对象
构造函数原理 ---构造函数与其他函数的区别----大驼峰式 Person
new 时
1.在函数体最前面隐式的创建this空对象 并给他添加原型链
2.执行函数体
3.隐式的返回this
包装类
new Number() new String() new Boolean()
var str = 'abcd';
str.length = 2 //str = 'abcd'
会进行隐式的转换调用new String('abcd').length = 2; 并delete
str.length //4
toString()
null 和 undefined 没有toString()方法是因为没有原型 而数字会进行包装类
inherit 继承函数
Father.prototype = {
lastName : '父亲的原型'
}
function Father(){
this.name = '父亲'
}
function Son(){
this.name = '儿子'
}
function inherit(Target, Origin){
function F(){};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.constructor = Target;
}
inherit(Son, Father)
var father = new Father();
var son = new Son();
对象的枚举 遍历
1.for in
2.hasOwnProperty()
3.in
4.instanceof A对象的 原型链上 有没有B的 原型
var obj ={ name:'Bob' }//obj.name == obj['name'] 属性查看
var liang= {
color1 : 'red',
color12 : 'green',
getColor : function(num){
console.log(this['color' + num])
}
}
var obj ={name:'xiaohong', eag:'15',color:'green'__proto__:{dudu:666} }
for(var key in obj){
if(obj.hasOwnProperty(key)){ //判断属性是否是自己的 原型上的不要
console.log(obj[key])
}
} 枚举时不能写obj.key因为会把它当变量
'dudu' in obj //true 只要是自己身上的属性都返回true
function F(){
}
var f = new F()
f instanceof F f instanceof Object //true
区别数组的3种方法
1.Object.prototype.toString.call()
2.instanceof
3.constructor
浅拷贝与深拷贝的区别
浅拷贝
方法1 for in
方法2 let newlist = Object.assign({},list)
方法3 let newlist = {...list}
深拷贝
方法1.obj1 = JSON.parse(JSON.stringify(obj))
方法1.function deepClone(Orinig, Target){
var Target = Target || {};
var tostr = Object.prototype.toString;
for(var key in Orinig){
if(Object.hasOwnProperty(key)){
if(typeof(Orinig[key]) !== 'null' && typeof(Orinig[key]) == "object"){
// origin[key] instanceof Array
tostr.call(Orinig[key]) == "[object Array]" ?
Target[key] = []:Target[key] = {}
deepClone(Orinig[key], Target[key])
}else{
Target[key] = Orinig[key]
}
}
}
return Target;
}
deepClone(obj, obj1)
call() apply() bind()
相同 改变this指向 借用用别人的方法 干自己的事 不同 传参列表不同,且bind()是新函数返回
function Person(name, age){
this.name = name;
this.age = age;
}
function Father(color){
this.color = color;
}
function Student(name, age ,color , tel , sex ){
Person.apply(this,[name, age])
Father.call(this, color)
this.tel = tel;
this.sex = sex;
}
var student = new Student('huang', 100, 'red', 15268883061, 'male');
const fn2 = fn1.bind({x:200})
fn2()
callee caller 区别
arguments.callee 解决递归自身名字问题
caller 返回自身在哪个函数里执行
function Test(n){
return n * arguments.callee *(n-1)
}
arguments.callee == Test 指向函数自身引用
function test(){
dome()
}
function dome(){
dome.caller //== Test 返回自身在哪个函数里执行
}
test();
重写push方法
Array.prototype.push = function(){
for(var i = 0 ; i < arguments.length ; i++){
this[this.length] = arguments[i]
}
return this.length;
}
类数组
属性为索引属性(数字),必须有length属性,最好加上push
好处是把数组对象特效拼在一起
坏处 方法需要手动添加
var obj = {
1:'a'
2:'b'
'length':2
'push':Array.prototype.push
'splice':Array.prototype.splie
}
push 的时候
Array.prototype.push = function(target){
obj[obj.length] = target
obj.length++
}
通过var在window上构造的基本属性,叫不可配置属性 不能直接删除
var a = 123;
window.a / detele 无效
arguments是个类数组 typeOf(arguments) == object
try{} catch(e)
try{
console.log('a')
console.log(b)----- 会直接跳catch执行 try里面发生错误 后面代码不执行
console.log('c')
}catch(e){//error
console.log('error.name') ---允许操作错误信息
}
理解json
json是js内置对象也是数据格式 内置两个方法 实现深拷贝
JSON.stringfiy() 解析为字符串
JSON.parse() 解析为json
js的内置函数有哪些
Function
String
Array
Date
Boolean
Number
Error
Object
RegExp
异步调用
前端调用异步状态
1.延迟任务 2.ajax调用数据 3.事件绑定
setTimeout(()=>alert ('hello world'),3000)
类型转换
1.强制类型转换
parseInt parseFloat toString
2.隐式
+字符串拼接、== 、if语句、逻辑运算 如 && ||
描述创建一个对象的过程
1.创建空对象绑定this
2.通过原型 链接到原型链
3.执行逻辑代码
4.返回对象(所以实例不用返回
可以跨域的3个标签
<img src=''> <script src=''> <link href=''>
Date
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)
toISOString() //YYYY-MM-DDTHH:mm:ss.sssZ 使用 ISO 标准返回 Date 对象的字符串格式:
提示页面性能的办法
1.减少http请求
2.异步加载
3.浏览器缓存
4.css中避免使用表达式
什么是浏览器缓存
资源文件在电脑磁盘上的备份
http的主要特点是什么
无连接 无状态
http常见的请求有哪些
1.GET获取资源
2.POST传输资源
3.PUT更新资源
4.DELETE删除资源
5.HEAD获取头部首部
GET 和 POST的差别
优势:
GET 请求会被浏览器会自动缓存 POST不会,除非手动设置
GET 在浏览器回退时无害,而POST会重新请求
劣势:
GET 请求不安全 参数在URL上 保存在浏览器中
GET 请求在url中参数有限制,POST没有
前端捕捉错误的方法
即时错误的捕捉
try-catch
window.onerror
数组的常用方法
改变数组
- shift() 删除第一项 返回被删除的值
- pop() 删除最后一项 返回被删除的值
- unshift() 在数组前面添加元素 返回数组长度
- push() 在数组后面添加元素 返回数组长度
- sort() 数组排序 a-b/b-a
- splice() 剪切(开始的下标,删除的个数,添加的个数) 返回数组
- reverse() 颠倒顺序 返回颠倒后的数组
- forEach() 遍历数组 无返回值
不改变数组
- join() 转换为字符串
- toString() 转换为string类型
- indexOf() 查找数组中是否包含某个元素 没有返回 -1 有返回 0
- includes() 查找数组中是否包含某个元素 返回true/false
- some() 数组是否至少有一项满足条件 true/false
- every() 数组是否所有项都满足条件 true/false 纯函数:不会改变原数组,没有副作用,且返回的是数组
- slice() 切片(从该下标开始截取,截取到下标) 返回区间内的数组
- filter() 过滤符合条件的元素 返回处理后的数组
- concat() 拼接 返回拼接后数组
- map() 遍历数组 返回处理后的数组
字符串的常用方法
- split() 拆分字符串
- indexOf()查找 未找到返回-1
- lastIndexOf() 从后朝前查找未找到返回-1
- slice() 截取字符串 开始到结束
- replace() 替换字符串
- toUpperCase()字符串转大写
- toLowerCase()字符串转小写
- concat() 连接字符串
for in for of的区别
for in 返回下标(key) for of 返回值(value)
Set Map 的用处
Set
let a = new Set([1,2,3,2,1]) 数组去重
console.log(a)//1,2,3
add():添加某个值,返回 Set 结构本身。
delete():删除某个值,返回一个布尔值,表示删除是否成功。
has():返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
Map
let tt = new Map([['gongzi',11],['fusu',22],['xiaobai',33]])
console.log(a.get('xiaobai')) //33
get() 获取值
set() //添加值
has(); // 查询是否存在
delete(); // 删除一个值
clear(); // 清空所有成员 无返回
方法
values()展示value
keys()展示key
entries() key和value一起展示
forEach()循环
主流浏览器
IE
chrome
safari
firefox
opera
es5严格模式
'use strict' 逻辑最顶端 (页面/局部函数顶端)
以下es3不能使用
1.with(obj){ //改变作用域链 直接的AO
}
2.arguments.callee caller
3.变量必须声明
4.局部this必须赋值 预编译局部this指向空 全局this还是指向windo
5.函数里不能有重复参数及对象里不能有重复属性
6.eval()改变作用域 直接执行字符串代码
js异步加载
1.defer 在dom渲染时并行加载,等dom渲染完了,多个按加载顺序执行,再执行DOMContentLoaded事件
2.async 在dom渲染时并行加载,加载完就执行,多个无顺序,加载时候不会阻碍dom渲染,执行时会
3.script标签 会优先下载并执行 再执行render three
1.var script = docunment.createElement('script');
2.script.Type = 'text/javascript'
//判断是否加载完成
3.script.scr = 'dome.js' //预加载
document.body.appendChild(script);//使用
script.onload = function(){}//保证下载完执行
浏览器出生时候一系列的事
document.readyState 页面的新生的实时状态
加载时 loading
解析完 interactive
加载执行完 complete
$(document).ready(function(){}) 解析完就
window.onload 全加载完才
跨域
1.JSONP
前台做限制
同源策略:协议 域名端口号 不一样即发生跨域
动态创建一个<script>标签 把请求通过参数发出去默认为callback
后端用参数的值作为函数名 js对象改为js代码作为参数返回给前端 以函数调用返回给前端
弊端
JSONP 后台需要做改动
只支持Get
发出去的不是XHR请求
2.被调用方解决(后端解决)
服务端在响应头里面
Access-Control-Allow-Origin:* 允许域名才能跨域,* 所有的域名都能访问,但是带cookie必须是全匹配,必须得指定域名
Access-Control-Allow-Methods:* 允许哪个方法访问我
Access-Control-Allow-Credentials:true/false 表示是否允许发送cookie,即cors请求中不包括cookie,设为true,即表示服务器明确cookie可以包含在请求中,一起发送给服务器
带Cookie的跨域
送的域名是调用方的Cookie
Access-Control-Allow-Origin:必须写域名
服务端判断Access-Control-Allow-Origin是否为空设置
自定义头的时候判断
服务端判断Access-Control-Allow-Headers是否为空设置
简单请求和非简单请求
1.简单请求 先执行后判断
方法为 GET POST HEAD
请求header里面没有自定义头
Content-Type 为
text/plain
multipart/form-data
application/x-www-form-urlencoded
2.非简单请的cors请求,是发送请求之后先在服务端 "预检" 一遍,预检发送的请求方法是 OPTIONS ,看看服务端是否允许跨域,假如我们使用PUT请求方法向后台发送请求,属于非简单请求,需要在node后台设置允许跨域
Access-Control-Max-Age: 18000 设置预检命令的缓存时间
disable cache 可以使缓存消失
得在前台页面写一个自定义的报文请求头属性content-type
方法为 PUT delete
Content-Type 为
发送json格式的ajax请求
自带定义头的ajax请求
2.调用方(前端解决)
多个域名指向
ES6
let const
1.先声明才能使用
2.不允许重复声明
3.不存在变量提升
4.块级作用域
5.不属于顶级对象window
const 常量 原始数据(栈)不可变 对象(堆)可以改变因为地址一样
Object.freeze(obj) 浅冻结 深冻结需要typeof 判断 Object.key()生成键数组
箭头函数没有this
沿着作用域链向上找this