前端开发总结

前端开发面试——试题简介

JS部分

解释一下变量提升

JavaScript引擎是通过先解析代码 获取所有声明的变量 然后再逐行向下运行 所以造成一个问题 就是所有变量声明的语句 都会被提升到代码顶部 这就叫做变量提升

console.log(a) // undefined
var a = 1

提升执行顺序

引擎将var a = 1拆分为 var a = undefineda = 1并且会提升var a = undefined放到顶端

简单描述一下闭包这个概念

闭包= 函数和函数内可访问变量的总和

  • 闭包的特点

    1. 函数内部总是可以访问其所在的外部函数中声明的参数和变量
    2. 使用
      3. 闭包的缺点:闭包会导致内存占用过高,因为变量都没有释放内存,从而垃圾回收机制不会销毁该变量
    function Person(){
       var name = 'wl';
       this.getName = function(){
           return name;
       }
       this.setName = function(value){
           name = value;
       }
    }
    const person = new Person()
    console.log(person.getName()) //wl
    person.setName('test')
    console.log(person.getName()) //test
    console.log(name) // undefined
    	// 解决办法二:
    	for (var j = 0; j < op.length; j++) {
    	  op[j].onclick = (function(j) {
    	    return function() {
    	      alert(j);
    	    };
    	  })(j);
    	}
    
      ### 垃圾回收原理
    

    垃圾回收原理博客
    1.js的垃圾回收机制是为了以防内存泄露。内存泄露的含义就是当已经不需要某块内存是,这快内存还存在者,垃圾回收机制就是不定期的寻找到不适用的变量,
    并释放掉他们所指向的内存。

js有哪些类型

1. 基本类型(原始类型):
   * String
   * Number
   * undefined
   * null
   * boolean
   * symbol(es6)
2. 引用类型
   * Object

js引用类型和基本类型有什么区别

  • 存储方式不同
  • 也就是说基本类型互不干扰 引用类型会指向相同的内存地址
  let a = 1
  let b
  b = a 
  b = 2
  console.log(a, b) // 1 2

  let obj = { name: 'test' }
  let obj2 = obj1
  obj2.name = 'bar'
  console.log(obj.name) // bar 
 * 栈内存和堆内存
 * 栈:存放基本类型,栈会自动分配内存空间,会自动释放,简单的数据段,占据固定的大小空间
 * 堆:存放引用类型,动态分配内存,大小不定也不会会自动释放,
 * 区别:栈所有在方法中定义的变量都是栈内存中,随着方法执行结束,这个方法的内存栈也会自然销毁。

null和undefined的区别

  • null表示空值 null本身是一个对象 是拥有指针地址的
  • undefined表示不存在

0.1 + 0.2为什么不等于0.3

  • 因为0.1和0.2被转换为二进制以后其实是无限循环的 但是js采取的浮点数裁剪方案会导致精度失效

  • 解决方案

    • ParseFloat((0.1 + 0.2).toFixed(10))
      

原形链的理解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ttrJE6Ki-1625026337021)(./assets/proto.jpg)]
详细解释在我的博客
1.所有的引用类型都可以自定义添加属性
2. 所有的引用类型都有自己的隐式原型(proto)
3. 函数都有自己的显示原型(prototype)
4. 所有的引用类型的隐式原型都指向对应构造函数的显示原型
5. 使用引用类型的某个自定义属性时,如果没有这个属性,会去该引用类型的proto(也就是对应构造函数的prototype)中去找

this的理解

  • 其实this只有三种情况
      1. 声明在全局的指向window
      1. 谁调用了某个函数 那么this就指向谁
      1. 对于new出来的一个对象 那么this指向对象本身

EventLoop

  • js优先执行同步代码 这属于宏任务 当js确认调用栈里没有宏任务以后 会扫描一遍微任务队列 如果发现有微任务 就会批量一次性执行队列里的所有微任务 每执行完一个宏任务都会伴生一个微任务队列
  • 宏任务:
    1. script标签
    2. setTimeout
    3. setInterval
    4. I/O
  • 微任务
    • promise
    • mutationObserver

深浅拷贝

1.浅拷贝:也就是只复制了第一层属性,复制对象是基本类型
在复制基本类型时,直接使用等号完成,在复制引用类型时,循环便利对象,对每个属性或值使用等号完成。
2. 深拷贝:对属性中所有引用类型的值,遍历到是基本类型的值为止,利用递归来实现深拷贝

### 递归的方法及什么地方常用
1.递归就是函数自己调用自己本身,或者在自己函数调用的下级函数中调用自己。、
```js
var data = [
 {
     name: "所有物品",
     children: [
         {
             name: "水果",
             children: [{name: "苹果", children: [{name: '青苹果'}, {name: '红苹果'}]}]
         },
         {
             name: '主食',
             children: [
                 {name: "米饭", children: [{name: '北方米饭'}, {name: '南方米饭'}]}
             ]
         },
         {
             name: '生活用品',
             children: [
                 {name: "电脑类", children: [{name: '联想电脑'}, {name: '苹果电脑'}]},
                 {name: "工具类", children: [{name: "锄头"}, {name: "锤子"}]},
                 {name: "生活用品", children: [{name: "洗发水"}, {name: "沐浴露"}]}
             ]
         }
  ]
}]
//普通遍历实现
var forFunction = function () {
    var str = ""
    data.forEach(function(row){
        row.children.forEach(function(row){
            row.children.forEach(function(row){
                row.children.forEach(function(row){
                    str += (row.name + ";")
                })
            })
        })
    })
    console.log(str)
}
forFunction()
//递归遍历实现
var recursiveFunction = function(){
    var str = ''
    const getStr = function(list){
        list.forEach(function(row){
            if(row.children){
                getStr(row.children)
            }else {
                str += row.name + ";"
            }
        })
    }
    getStr(data)
    console.log(str)
}
recursiveFunction()
```

new运算符做了什么

1. 一个新的对象被创建 继承自构造函数的prototype  foo.prototype
2. 构造函数被执行传入参数 以及this this指向这个新的实例
3. 判断构造函数是否返回了对象 如果是返回的数据结构是一个对象 那么就会取代new 如果没有 那么就是第一步创建的对象

###继承
1.原型链继承(将父类的实例作为子类的原型)
特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
  缺点:1、新实例无法向父类构造函数传参。
     2、继承单一。
     3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
2. 借用构造函数继承
特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
       2、解决了原型链继承缺点1、2、3。
       3、可以继承多个构造函数属性(call多个)。
       4、在子实例中可向父实例传参。
    缺点:1、只能继承父类构造函数的属性。
       2、无法实现构造函数的复用。(每次用每次都要重新调用)
       3、每个新实例都有父类构造函数的副本,臃肿。
3. 组合继承
重点:结合了两种模式的优点,传参和复用
  特点:1、可以继承父类原型上的属性,可以传参,可复用。
     2、每个新实例引入的构造函数属性是私有的。
  缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
4. 原型式继承
重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
    特点:类似于复制一个对象,用函数来包装。
    缺点:1、所有实例都会继承原型上的属性。
       2、无法实现复用。(新实例属性都是后面添加的)
5. 寄生式继承
重点:就是给原型式继承外面套了个壳子。
    优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。
    缺点:没用到原型,无法复用。
6. 寄生组合式继承
寄生:在函数内返回对象然后调用
    组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参 
重点:修复了组合继承的问题

ES Module 和 CommonJS Module区别

  • ES Moudule是静态引入的
  • Common JS是动态引入的
  • 前者支持tree shaking 后者不支持

###Promise 原理
1.promise 是一种异步编程的解决方案。用于解决回调地狱的问题。
2.promise 是事件循环中的微任务。在每次事情循环中会清空了微任务队列。
3.promise 一旦执行无法中途取消
4.promise的错误无法在外部被捕捉到,只能在内部进行预判处理
5.在promise内如何执行的,监测起来很难。

promise对象存在三种状态:pending(进行中) Fulfolled(已成功) Rejected(已失败)
resove和reject 改变promise的状态 将接受的值作为promise 的value

Vue面试题

Vue的核心

  • 数据驱动视图(MVVM) + 组件化

双向绑定的原理

Object.definePrototy getter setter 网上随便搜一下 多的很
  getter 是调用了这个方法
  setter 是数据更新了返我
  configurable:true, //默认false, 是否可删除

Vue watch 与computed的区别

watch的使用场景是在data中某个数据发生变化时或者需要在数据变化执行异步
watch 普通监听跟深度监听 (使用handler 的immediate属性 可以立即执行)
deep 为true 可以深度监听某个对象的值。
相同点:他们两者都会观察页面数据变化的
不同点:computed只有当依赖的数据发生变化时才会计算,当数据没有变化时,它会读取缓存数据
				watch每次都需要执行函数,wacth更适用数据变化是的异步操作。
computed原理

Vue为什么监听不到对象和数组

  • 因为引用类型是存放在堆内存里的 平时我们操作的引用类型其实是存放在栈内存里的一份拷贝 所以无法监听到

data为什么要是函数

  • 函数作用域 防止不同组件相同变量造成的污染

描述一下Vue初次更新和数据更新的过程

  • 初次更新
    • 解析模板为render
    • 触发obj.defineProptryty的getter
    • 执行render 生成VNode
    • patch(ele, VNode)
  • 数据更新
    • 触发```obj.defineProptry``的setter
    • 执行render 生成VNode
    • patch(oldVnode, newVnode)

Vue的diff算法

  • 新旧节点通过 首尾比较 新头旧尾 新尾旧头四种比较方式来做diff比较
  • 当4中方式都无法匹配的时候 会用到key 所以key最好是唯一值 不能是index 因为index会变化

Vue的Compiler过程

Complie的主要作用就是解析模板,生成渲染模板的render,render的作用主要是为了生成Vnode
  • parse - optimize - generate
  • parse 接受template原始模板,按着模板的节点和数据生成对应的ast
  • optimize 遍历ast的每一个节点,标记静态节点,这样就知道哪部分不会变化,于是在页面需要更新时,减少去对比这部分DOM,提升性能
  • generate 把前两步生成完善的ast,组成render字符串,然后将render字符串通过new Function的方式转换成渲染函数

描述一下Vuex

  • 首先vuex适用于一些同级组件或者完全八竿子打不着关系的组件之间进行传值
  • state: 组件之间需要公用的值 可以存放在state里
  • actions: 存放的是异步操作或者是批量的同步操作 组件通过dispatch调用actions
  • mutations: 存放的是一些同步方法 对state的修改 actions通过commit调用
  • actions和mutations最大的区别就是前者是异步的后者是同步的

尝试用js模拟vnode

// html代码<div class="div-container" id="div">  <p>vnode</p>  <div>    <p style="font-size: 12px">try to describe V-node by using js</p>  </div> </div>
// 用js对象模拟出的vnode
{
tag: 'div',
props: {
  className: 'div-container',
  id: 'div'
},
children: [
  {
    tag: 'p',
    children: 'vnode'
  },
  {
    tag: 'div',
    children: [
      tag: 'p',
      props: {
        style: 'font-size: 20px'
      },
      children: 'try to describe V-node by using js'
    ]
  }
]
}

Vue-Router实现原理

  • 首先有两种模式hashhistory
  • hash实现原理: 监听window.hashOnChange事件 hash模式路由带#号
  • history利用了html5新出的API pushStatepopState

父子组件生命周期

  • 父beforeCreated -> 父created -> 父beforeMounted -> 子beforeCreated -> 子created -> 子beforeMounted -> 子mounted -> 父mounted

Webpack面试题

devser
##性能优化
1. css 压缩css optimize-css-assetsWebpackPlugin mini-css-extrect-plugin
2. js 压缩生产环境自动压缩 mode:'production' html 压缩再htmlPlugin minfigy的两个属性 js按序加载usage
3. 优化配置 一半分为2种,开发环境和生产环境, 
##开发环境 优化打包构建速度。 优化代码调试。
*HMR 模块热替换 构建速度会更快 
*source-map 如果构建后代码出错了,通过构建后提示错误信息
##生产环境 优化打包构建速度 。优化代码性能
*打包速度oneOf -- babel 缓存
_dll 对第三方的库再次进行打包 DllLinkPlugin
通过cnd 链接引用 externals
*缓存(hash-chunkhash-contenthash)
*优化性能的 tree shaking //必须es6,会自动清除没用的代码的 sideEffect:[注释起来]
4。code spliting 代码分割  单入口-就是一个bundle配置向多个 (通过import引入的js 代码就会分割) commonsChunkPlugin

5.懒加载,预加载
6.pwa 是离线打包技术 离线也可以访问 workboxwebpackPlugin.get
7.多进程打包,可以提示打包 速度

### webpack中都有用到那些插件
	1.optimize-css-assetsWebpackPlugin css 压缩
	2. speed-measure-webpack-plugin 打包速度分析 这个不是在plugin中引入。而是先实例化,smp.wrap()方法包裹
	3. webpack-bundle-analyzer 体积分析
	4. terser-webpack-plugin 多进程多实例并进行代码压缩 optimization 中进行压缩
	5. CommonsChunkPlugin  DLLPlugin 就是把第三方库和我们自己的代码分开,每次只打包项目自身代码

module bundle chunk的区别

  • module - 源码文件(模块)
  • chunk - 多个模块合成的代码
  • bundle - 输出文件

Loader和Plugin的区别

  • Loader是翻译器 帮助webpack识别该如何打包对应类型的文件
  • Plugin会在webpack对应的生命周期自动帮我们做某件事

Webpack构建流程

  • 初始化参数: 通过shell命令以及config.js合并参数
  • 开始编译: 通过参数初始化Compiler对象 执行run方法
  • 确定入口: 根据entry确定入口
  • 编译模块: 从入口文件开始 利用loader开始翻译 并且通过递归来确定所有依赖的文件都已确立相互的依赖关系
  • 输出资源
  • 写入内存

利用webpack优化性能

1. 优化```sourcemap```
2. 利用CDN加速 => 静态资源路径修改为cdn路径
3. 利用```Tree shaking```默认开启 只支持es6 Moudle
4. code spliting(代码分割 你随便搜一下 很多的 其实就是配置项)

提高webpack打包效率

  1. happyPack

  2. dll打包

  3. 减少loader的搜索范围 loader可以配置exclude 因为node_modules 其实是已经打好包了 所以第三方文件不需要再次打包

    ###跨域如何解决的

    1. jsop jsonp的话请求一定需要对方服务器的支持才可以,优点是简单兼容性好,缺点是🈲支持get方法,具有局限性,不安全
    2. cors CORS需要

输入URl发生什么

	1.域名解析,浏览器将url解析出相应的服务器的IP地址	2. 浏览器与目标服务器建立一条Tcp链接(三次握手)	3. 浏览器向服务器发送一次Http请求报文	4. 服务器返回浏览器一条HTTP响应报文	5. 浏览器进行渲染	6. 关闭TCP链接,四次挥手*浏览器渲染的步骤1.html解析出Dom2.css解析出style Rules3.两者关联生成render4.layout布局根据render计算每个节点信息5.painting 根据计算好的信息进行渲染页面

强制缓存和协商缓存

强制缓存是在我们第一次请求资源是在http响应头设置一个过期时间,在有效时间内都将直接从浏览器中进行获取,常见的http响应头字段如cache-Control 和Expires协商缓存是我们通过http响应头字段etag或者last-Modified等判断服务器上的资源是否修改,如果修改则从服务器重新获取,如果没修改则304指向浏览器器缓存获取

###http1.0/1.1/2.0
1.HTTP1.0定义了三种请求方法:get post head。1.1新增了六种请求方法:optoions put patch delete trace connect
2.缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,
HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
3.host头处理:
4.长链接

##2.0与和1.1相比
新的二进制格式(Binary Format):HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,
		要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。
		基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用(MultiPlexing):即连接共享,即每一个request都是是用作连接共享机制的。
	一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,
	接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
header压缩:如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,
		HTTP2.0使用了专门为首部压缩而设计的 HPACK 算法,使用encoder来减少需要传输的header大小,
		通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送(server push):服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。
		正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。
		例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,
		服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。

###http状态码
1xxx 临时响应表示临时响应并需要请求者继续执行操作的状态码
2xx(成功)表示成功处理了请求的状态码
3xx(重定向)表示要完成请求,需要进一步操作;通常,这些状态代码用来重定向
4xx(请求错误)这些状态码表示请求可能出错,妨碍了服务器的处理
5xx(服务器错误)这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错

/1.对数组的结构
// const ARRAY = [ '小石','小王']
// let [ xs, xw ] = ARRAY
// console.log(xs)

//es6的模板字符串
	//内容中可以直接出现换行
	// 2.变量的拼接
	// let a = '小石'
	// let b = `${a}是小仙女`;
	// console.log(b)
	
//es6对象的简化写法
	// let name ='1';
	// const obj ={
	// 	name
	// }
	
//箭头函数
	// 1.箭头函数的特性
		// this是静态的,this始终指向函数声明是所在作用下的this的值
		//call方法调用
	// 2.不能作为构造实例化对象
	// 箭头函数没有rutuen 
	// let arr =[
	// 	{
	// 		id:'1',
	// 		c:[
	// 			{
	// 				id:2,
	// 			},
	// 			{
	// 				id:3,
	// 			}
	// 		]
	// 	}
	// ];
	// let c;
	// let res = arr.filter(item =>{
	// 	c = item.c.filter(child => child.id==2)
	// })
	// console.log(c)

	//rest 参数
	// args参数必须放到最后
	// function date(...args) {
	// 	console.log(args)
	// }
	// date({id:'1',name:'wl'})
	
	//拓展运算
	// let arr =['wk','li1']
	// function box() {
	// 	console.log(arguments)
	// }
	// box(...arr)
	
	//symbol 数据类型 是类似字符串的
	
	//对象循环
	// let user = {name:1,id:'2'}
	// for(let [key, vlaue] of Object.entries(user)) {
	// 	console.log(`${key}`)
	// }
	// let user = new Map()
	// user.set('name', 'John')
	// user.set('age', '30')
	
	// for (let [key, value] of user.entries()) {
	//   console.log(`${key}:${value}`) // name:John, then age:30
	// }
	
	//数组循环 Array
	let arr = [1,2,4,5,7]
	// arr.forEach(function(elem, index, array) {
	//     if (arr[i] == 2) {
	//         continue
	//     }
	//     console.log(elem, index)
	// })
	//forEach 不支持continue 及break
	
	//map 返回新的数组 每个元素为调用func的结果
	// let result = arr.map(function(value) {
	//     value += 1
	//     console.log(value)
	//     return value
	// })
	// console.log(arr, result)
	
	//filter() 返回符合条件的元素数组
	// let result = arr.filter(value => value==2)
	// console.log(arr, result)
	
	// some() 返回的boolean, 判断是否有元素符合的func条件
	// let ret = arr.some(item => item==8)
	// console.log(arr, ret)
	
	//every() 返回boolean ,判断每个元素都符合func条件
	// let ret = arr.every(item =>{
	// 	console.log(item)
		
	// 	item ==7
	// })
	// console.log(arr, ret)
	
	//reduce() 接受一个函数作为累加器
	// let sum = arr.reduce(function(prev, cur, index, array) {
	//     return prev + cur
	// }, 0)
	// console.log(sum)
	// let max = arr.reduce(function(prev, cur) {
	//     return Math.max(prev, cur)
	// })
	// console.log(max)
	// let res = arr.reduce(function(prev, cur) {
	//     prev.indexOf(cur) == -1 && prev.push(cur)
	//     return prev
	// }, [])
	// console.log(res)

	//es6 中数组遍历方式
	// for (let item of arr) {
	//     console.log(item)
	// 		// if(item ==4) {
	// 		// 	break
	// 		// }
	// }
	
	// for (let item of arr.values()) {
	//     console.log(item)
	// }
	
	// for (let item of arr.keys()) {
	//     console.log(item)
	// }
	// for (let [index, item] of arr.entries()) {
	//     console.log(index, item)
	// }
	
	//Array.from()
	// let arrLike = {
	//     0: 'a',
	//     1: 'b',
	//     2: 'c',
	//     length: 3
	// }
	// let ret = Array.from({
	//     length: 3
	// }, function() {
	//     return arrLike
	// })
	// console.log(ret)
	
	//Array.fill()
	// fill()方法用一个固定值填充一个数组中从起始索引内的全部元素,不包括终止索引.
	// arr.fill(9,3,4) //第一个元素是替换值 //第二个是开始值第三是结束值
	// console.log(arr)
	
	//Array.find() //返回数组中,满足第一个元素的值
	// let ret = arr.find(item => item<5)
	// console.log(ret)
	// let ret = arr.findIndex(item => item==5)
	// console.log(ret)
	
	//Array.copyWithin() //在当前数组内部,将指定位置的成员复制到其他位置然后返回当前数组
	// console.log(arr.copyWithin(1,3))
	
	//function 箭头函数
	 // let pow = x => x * x
	 // console.log(pow(2))


	//Object 复制对象 并相同替换
	// const obj={
	// 	id:1,
	// 	name: 'w'
	// }
	// const obj2 ={
	// 	name: 'wl'
	// }
	// const obj3 = Object.assign(obj,obj2)
	// console.log(obj3)
	
	//class 声明类
	// class Animal {
	//     constructor(type) {
	//         this.type = type
	//     }
	//     walk() {
	//         console.log( `I am walking` )
	//     }
	// }
	// let dog = new Animal('dog')
	// let monkey = new Animal('monkey')
	// console.log(dog,monkey)
	
	// class Animal {
	//     constructor(type) {
	//         this.type = type
					
	//     }
	//     walk() {
	//         console.log( `I am walking` )
	//     }
	//     static eat() {
	//         console.log( `I am eating` )
	//     }
	// }
	// let dog = new Animal()
	// console.log(dog.eat())

	// Symbol
	// const grade = {
	//     张三: {
	//         address: 'xxx',
	//         tel: '111'
	//     },
	//     李四: {
	//         address: 'yyy',
	//         tel: '222'
	//     },
	//     李四: {
	//         address: 'zzz',
	//         tel: '333'
	//     },
	// }
	// console.log(grade)
	// const stu1 = Symbol('李四')
	// const stu2 = Symbol('李四')
	// const grade = {
	//     [stu1]: {
	//         address: 'yyy',
	//         tel: '222'
	//     },
	//     [stu2]: {
	//         address: 'zzz',
	//         tel: '333'
	//     },
	// }
	// console.log(grade)
	// console.log(grade[stu1])
	// console.log(grade[stu2])
	// const sym = Symbol('imooc')
	// class User {
	//     constructor(name) {
	//         this.name = name
	//         this[sym] = 'imooc.com'
	//     }
	//     getName() {
	//         return this.name + this[sym]
	//     }
	// }
	// const user = new User('xiecheng')
	// console.log(user.getName())
	
	// for (let key in user) {
	//     console.log(key)
	// }
	
	// for (let key of Object.keys(user)) {
	//     console.log(key)
	// }
	
	// for (let key of Object.getOwnPropertySymbols(user)) {
	//     console.log(key)
	// }
	
	// for (let key of Reflect.ownKeys(user)) {
	//     console.log(key)
	// }

	//消除魔术字符串
	// const shapeType = {
	//     triangle: Symbol(),
	//     circle: Symbol()
	// }
	
	// function getArea(shape) {
	//     let area = 0
	//     switch (shape) {
	//         case shapeType.triangle:
	//             area = 1
	//             break
	//         case shapeType.circle:
	//             area = 2
	//             break
	//     }
	//     return area
	// }
	// console.log(getArea(shapeType.triangle))
	
	//set
	// let arr1 = [1, 2, 3, 4]
	// let arr2 = [2, 3, 4, 5, 6]
	//  // 交集
	// let s1 = new Set(arr1)
	// let s2 = new Set(arr2)
	// let result = new Set(arr1.filter(item => s2.has(item)))
	// console.log(Array.from(result))
	// // 差集
	// let arr3 = new Set(arr1.filter(item => !s2.has(item)))
	// let arr4 = new Set(arr2.filter(item => !s1.has(item)))
	// console.log(arr3)
	// console.log(arr4)
	// console.log([...arr3, ...arr4])
	
	// const str = 'imooc'
	
	// console.log(str.includes('mo'))
	// console.log(str.startsWith('im'))
	// console.log(str.endsWith('mooc'))
	// const newStr = str.repeat(10)
	
	// console.log(newStr)


	// Number 二进制
	// Number.isFinite()
	// 用来检查一个数值是否为有限的(finite),即不是Infinity。
	// Number.isFinite(15) // true
	// Number.isFinite(0.8) // true
	// Number.isFinite(NaN) // false
	// Number.isFinite(Infinity) // false
	// Number.isFinite(-Infinity) // false
	// Number.isFinite('foo') // false
	// Number.isFinite('15') // false
	// Number.isFinite(true) // false
	
	// const a = 0B0101
	// console.log(a)
	// const b = 0O777
	// console.log(b)
	
	// Number.isInteger() //用来判断一个数值是否为整数
	
	// Math.trunc()方法用于去除一个数的小数部分,返回整数部分。
	// console.log(Math.trunc(5.5))
	// console.log(Math.trunc(-5.5))
	
	//Proxy
	// let o = {
	//     name: 'xiaoming',
	//     age: 20
	// }
	
	// let handler = {
	//     get(obj, key) {
	//         return Reflect.has(obj, key) ? obj[key] : ''
	//     }
	// }
	
	// let p = new Proxy(o, handler)
	
	// console.log(p.name)
	
	// Promise .reject()
	// new Promise(function(resolve) {
	//     resolve(42)
	// })
	// Promise.resolve(42).then(function(value) {
	//     console.log(value)
	// })
	// var p1 = Promise.resolve(1)
	// var p2 = Promise.resolve(2)
	// var p3 = Promise.resolve(3)
	// Promise.all([p1, p2, p3]).then(function(results) {
	//     console.log(results) // [1, 2, 3]
	// })
	// function getPromise(url) {
	//     return new Promise((resolve, reject) => {
	//         ajax(url, res => {
	//             resolve(res)
	//         }, err => {
	//             reject(err)
	//         })
	//     })
	// }
	
	// getPromise('static/a.json')
	//     .then(res => {
	//         console.log(res)
	//         return getPromise('static/b.json')
	//     }).then(res => {
	//         console.log(res)
	//         return getPromise('static/c.json')
	//     }).then(res => {
	//         console.log(res)
	//     }).catch(err => {
	//         console.log(err)
	//     })

	//git 撤销最近一次提交
	// git reset HEAD^
	//git push -f 强制推送
	//git brabch -a 查看清理远程分支
	// git push origin --delete dev
	// git remote show origin //查看远程仓库信息
	 //git branch -d 清除本地分支
	 // git remote -v 查看当前仓库地址
	 // git remote add 添加仓库地址 set 是删除
	 // 使用 git fetch 拉取远程仓库信息(不会自动进行合并);
	 // 使用 git reset --hard origin/分支名 命令将远程仓库完全覆盖本地仓库。
	 //git revert
	 // git reset 命令会改变之前的版本记录,可能会导致不能提交到远程仓库;
	 // git revert命令只会撤销某个版本的代码,然后在当前分支增加一条版本新记录;
	 // git revert 只会撤销指定版本的代码,而不是指定版本后的所有版本。
	 //git reflog  恢复
	 //git rebase 与git merge 功能类似,可以记录版本变化,可以好修改撤销
	 // git merge 命令合并之后,版本记录会按照时间顺序,并自动产生一个merge branch的版本
	 //git cherry-pick 将另外的一个分支合并

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…