TypeScript

1.可兼容JavaScript;相比js,加入了注释;添加一个完整的类结构,更好的面向对象;

2.Mac OS X环境搭建:

2.1.安装homebrew(套件管理器)官网:brew.sh:

ruby -e "$(curl -fsSL 
https://raw.githubusercontent.com/Homebrew/install/master/install)" 

2.2安装npm(nodejs包管理器):

brew install node

2.3.安装typescript(安装成功后,可以键入tsc测试):

npm install -g typescript
tsc

3.IDE中新建typescript文件,添加watcher实现自动编译

也可以用命令的方式编译一个ts文件为js文件:终端目录下,tsc xx.ts,会生成同名js文件

4.TypeScript 7种 基础数据类型:

Boolean:

var isBone: boolean = false; //使用时要给个初始化的值

Number:

var height: number = 6;

String:

var name: string = "bob";

Array:

var list: number[] = [1, 2, 3]; 
// 或者
var list: Array<string> = [ "joe", ”kevin” ];

获取数组中数据:

List[0];

Enum:

枚举类型:有一定范围的数据可以用枚举类型最好

enum Color {Red, Green, Blue};var colorName:string = Color[1];console...

枚举类型还可以进行(数组)下标赋值操作:

enum Color {Red = 10, Green = 12, Blue = 13};
var colorName: string = Color[12]; // Green
// 获取下标:
var c:Color = Color.Green; // 1

Any:

任意类型:可以多次赋值,后面的会覆盖前面的。

var notSure: any = 10;
notSure = "hello";

也可以指定类型,如下指定为数组

Var list: any[ ] =  [1, “hello”, false];
List[2] // false

Void:

对函数进行声明:

function tell( ):string{return  "hello";
}

不需要任何返回值,就可以把函数声明为void

function tell1( ):void{}

类:

创建一个类:

class Preson{// 属性name:string;age:number;// 构造方法constructor(name:string, age:number){this.name = name;this.age = age;}// 普通方法print(){return this.name + " : " + this.age;}
}

调用这个类:

var p = new Person(“mike”, 10);
p.print();

类的继承

无构造函数的类的继承:

class Person{name: string;age: number;tell(){return this.name + ":" + this.age;}
}class Student extends Person{school: string;tell(){return this.name + ":" + this.age + ":" + this.school; }
}
var s = new Student("捷克学院");
// 没有构造函数,无法使用参数,就用如下方式传入参数值
s.name = "jack";
s.age = 23;
s.school = "捷克学院";
// 执行
s.tell();

有构造函数的类的继承:

class Person{name: string;age: number;constructor(name:string, age:number){this.name = name;this.age = age;}tell(){return this.name + ":" + this.age;}
}class Student extends Person{school: string;constructor(school:string){// 修改父类的参数,super要写在最前面super("ime", 23);this.school = school;}tell(){return this.name + ":" + this.age + ":" + this.school; }
}
var s = new Student("捷克学院");
// s.name = "jack";
// s.age = 23;
// s.school = "捷克学院";
s.tell();

访问修饰符

公有:public(默认)
私有:private

class Person{public name: string; /*** 默认就是public,如果我在这里写private,* 或者在下面constructor参数中这样写:private name:string,* 那么继承自它的 Student 就无法访问到 name 这个属性了**/age: number;constructor(name:string, age:number){this.name = name;this.age = age;}tell(){return this.name + ":" + this.age;}
}class Student extends Person{school: string;constructor(school:string){this.school = school;super("ime", 23);}tell(){return this.name + ":" + this.age + ":" + this.school; }
}
var s = new Student("捷克学院");
// s.name = "jack";
// s.age = 23;
// s.school = "捷克学院";
s.tell();

封装的实现

· 利用private实现的私有属性,可以在类中通过getter和setter来对外开发(私有属性或方法)接口
· 在调用方法时,getter和setter会默认执行

class Hello{private _age:number;show(){return this._age; }get age():number{// 可对外开发私有属性return this._age;}set age(newage:number){// 可修改私有属性if(newage >200 || newage < 0){alert("请输入正确的年龄");}else{this._age = newage;}}
}var h = new Hello();
h.age = 300;
alert(h.tell());

static(静态)和其使用技巧

类的属性或方法(非静态),可以通过实例化对象调用,如下:

class Person{name:string;tell(){alert("姓名:" + this.name);}
}var p = new Person();
p.name = "hello";
p.tell();

但一旦属性或方法声明为Static后,就变为了静态属性 / 静态方法
不能再通过实例化对象调用,必须通过类本身调用:

class Person{static name:string;tell(){alert("姓名:" + Person.name);}
}var p = new Person();
Person.name = "hello";
p.tell();

static静态的使用(进阶)技巧:引用数据类型

class Greeter{greeting:string;constructor(msg:string){this.greeting = msg;}greet(){return "Hello," + this.greeting;}
}
/**
创建一个类型,指定它的类型为当前类的类型;
其实,创建了一个类,也就是创建了一个声明,
可以把当前数据的类型,声明为当前类的类型
我们称它为“引用数据类型”
**/
var green:Greeter;
green = new Greeter("mike");
alert(green.greet());

函数:函数类型

函数有 命名函数 和 匿名函数,在Ts中,可以指定函数参数的类型和函数本身(返回值)的类型:

// 命名函数
function add(x:number, y:number):string{// 如果返回值的类型不是函数指定的类型,就会报错// 例如:return x+y;就会报错return "hello ts";// 类型相符,不会报错
}
// 匿名函数(在js中,上面的命名函数是这种方式的语法糖)
var myadd = function(x:number, y:string):string{return "hello ts";
}

上面的x,y,并不清楚其意义,我们可以让参数更明确其意义:

/** 
* "=>" 前面可以声明参数的语义化名称和类型
* "=>" 后面紧跟着函数类型
**/
var myAddts:(name:string, age:number) => number = function(n, a){return a;
}

函数:可选和默认参数

可选参数:用 ?表示,可传可不传

function buildName(firstName:string, lastName?:string){if(lastName){return fristName + " " + lastName;} else {return firstName;}
}
// 均不会报错
var result1 = buildName("james", "bonde");
var result2 = buildName("bonde");
// 超出最大的参数个数,则会报错
// var result3 = buildName("james", "bonde", "valin"); 

默认参数:直接在参数上赋值

function buildName(firstName:string, lastName="bonde"){return firstName + " and " + lastName;
}
// 可以只传一个参数,也可以传两个参数,传两个,则会覆盖默认参数值
var result1 = buildName("Hello: ");
var result2 = buildName("james", "wade");
// 超出最大的参数个数,仍旧会报错
// var result3 = buildName("james", "bonde", "valin"); 

函数:可变参数

利用es6的扩展运算符(展开运算符)

function peopleName(firstName:string, ...restOfName:string[]){// restOfName:string[] 代表数据类型为字符串的数组return firstName + " " + restOfName.join(" ");
}
// 利用可变参数,可以传递无数个参数,在需要传入不确定参数个数时,很好用
var pn = peolpleName("jack", "mary", "honly", "kevin"...);

Lambads 和 this 关键字的使用

var people = {name:["iwen","ime","if","bean"];getName:function(){return function(){var i = Math.floor(Math.random()*4);return {n:this.name[i]}}}
}var myName = people.getName();
alert("名字:" + myName().n); // 这是访问不到的

此时这个this指向的不是people。调用发现getName中的this关键字指向的是getName,访问不到外部的name属性。

可以用lambads表达式"()=>"修改,箭头函数能保存函数创建时的 this值,而不是调用时的值。

var people = {name:["iwen","ime","if","bean"];getName:function(){return () => {var i = Math.floor(Math.random()*4);return {// 这里的this代表函数创建时的this,因此可以访问到name属性n:this.name[i]}}}
}var myName = people.getName();
alert("名字:" + myName().n); // 此时可访问

TypeScript 的重载

function attr(name:string):string;
fucntion attr(age:number):number;function attr(nameOrAge:any):any{if(nameOrAge && typeof nameOrAge === "string"){  alert("姓名");}else{alert("年龄");}}/**
*  在某些编程语言中,函数重载或方法重载是指能够创建具有不同实现的同名方法。
*  对重载函数的调用将运行与调用上下文相适应的该函数的特定实现,
*  允许一个函数调用根据上下文执行不同的任务。
*  这里如果有不清楚可以看一下这里:https://www.zhihu.com/question/63751258
**/
attr("Hello");
attr(19);

接口-创建接口

// 规范了参数的类型
function printeLabel(labelObj:{label:string}){console.log(labelObj.label);
}
var myObj = {label:"Hello"};
// var myObj = {label:10};
printeLabel(myObj);

接口-可选属性

interface USB{name:string;age:number;
}
function printUSB(pu:USB){console.log(pu.name);
}
// 如果不定义参数可选,my必须包含两个参数,即string类型的name和number类型的age,否则编译会报错
var my = {name: "ime", age: 100};
printUSB(my);

可选参数通过 " ?"定义

interface USB{name?:string;age?:number;
}
function printUSB(pu:USB){console.log(pu.name);
}
// 定义了参数可选,my就可以按照可选参数传递参数了。
var my = {name: "ime"};
printUSB(my);

接口-函数类型

用接口的类型 来 规定函数的类型

interface SearchFunc{(source:string, subString:string):boolean;
}
// 定义函数的类型为接口的类型
var mySearch:SearchFunc:
mySearch = function(src:string, sub:string){var result = src.search(sub);if(result != -1){return true;}else{return false;}
}

接口-数组类型

使用接口对数组进行规范化

interface StringArray{/*** 数组中index对应的是一个number类型,但数组最终返回的是一个string类型* 可理解为下标是number类型;数组中的数据是字符串类型
**/[index:number]:string; 
}var myArray:StringArray;
// 规定了数组中必须是string类型,其他类型都不可以,即使为空,也必须是空字符串。
myArray = ["10", "12"];
alert(myArray[1]);

接口-class类型

interface ClockInterface{currentTime:Date;setTime(d:Date);
}
class Clock implements ClockInterface{currentTime:Date;setTime(d:Date){this.currentTime = d;}constructor(h:number; m:number){}
}

接口 - 接口继承与混合类型

接口的继承:

interface Shape{color:string;
}
interface PenStroke{penWidth:number;
}
interface Square extends Shape,PenStroke{sideLength:number;
}var s = <Square>{}; // 将一个接口初始化在一个变量中
s.color = "blue";
s.penWidth = 10;
s.sideLength = 10;

接口的混合类型:

interface Counter{interval:number;reset():void;(start:number):string;
}var c:Counter;
c(10);
c.reset();
...

认识泛型

可以让参数类型在使用时才指定类型,而不需要在方法定义时就指定,这样使用更加灵活;它相比于any类型,在使用方法时有更好的明确性。

function Hello(num:number):number{return num; // 必须是number类型
}
function hello(str:any):any{return str; // 可以是任意类型
}
// 泛型一般用<T>表示,也可以用其他的大写字母
function hello<T>(arg:T):T{return arg; // 在调用之前可以是任意类型
}
// 调用时指定参数类型后,就必须是这种类型
var output = hello<string>("world");

泛型的使用

(后续补充)

Vue

对MVVM开发模式的理解

Model:代表数据模型,数据和业务逻辑都在Model层中定义;
View:代表UI视图,负责数据的展示;
ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;

Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。

这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。

Vue 有哪些指令?

v-html、v-text、v-show、v-if、v-for等

v-if 和 v-show 的区别

v-show 仅仅控制元素的显示方式,将 display 属性在 block 和 none 来回切换;而v-if会控制这个 DOM 节点的存在与否。当我们需要经常切换某个元素的显示/隐藏时,使用v-show会更加节省性能上的开销;当只需要一次显示或隐藏时,使用v-if更加合理。

简述Vue的响应式原理

当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。
用ES5实现:

// 第一步 实现基本架构
// 第二步 把模型的数据 显示到视图
// 第三步  更新视图同步到模型,再更新视图
// 发布者
class Vue{constructor(options){this.options = options;this.$data = options.data;this.$el = document.querySelector(options,el);this._directives = {// 存放订阅者集合的数组对象  }this.Observer(this.$data);this.Compile(this.$el);}// 劫持数据Observer(data){// 更新视图  局部更新for(let key in data){this._driectives[key] = []; // 空类数组对象let val = data[key]; // 当前的值 let _this = this;Object.defineProperty(this.$data, key, {get: function(){return val;},set: function(newVal){if(newVal !== val){val = newVal;//_this._directives[key] 得到myText的数组_this._directives[key].forEach(watch=>{// 遍历订阅者的实例watch.update(); // 更新视图})}}});}}// 解析指令Compile(el){let nodes = el.children;] // 获取APP下面的子元素for(let i = 0;i < nodes.length; i++){let node = nodes[i]; // 当前元素if(node.children.length){// 如果当前元素含有子元素,就递归调用自己this.Compile(node);}if(node.hasAttribute('v-text')){// 获取属性值,对号加入对应的订阅者数组let attrVal = node.getAttribute("v-text")this._directives[attrVal].push(new Watcher(node, attrVal, this, 'innerHTML'));}if(node.hasAttribute('v-model')){let attrVal = node.getAttribute("v-model");this._directives[attrVal].push(new Watcher(node, attrVal, this, 'value'));// 监听文本框事件node.addEventListener('input', (function(){return function(){// console.log(node.value);// 更新视图到模型this.$data[attrVal] = node.value;}})());}}}class Watcher{constructor(el, vm, mySelf, attr){this.el = el; this.el = vm; this.el = mySelf; this.el = attr; this.update(); // 初始化数据}update(){// div对象[innerHTML] = vue对象.data['myText']// input对象[value] = vue对象.data['myText']this.el[this.attr] = this.mySelf.$data[this.vm];}}
}

在Vue3.0版本中式采用ES6的Proxy对象来实现。

// 获取段落节点
const paragraph = document.getElementById('pararaph');
// 获取输入框节点
const input = document.getElementById('input');// 需要代理的数据对象
const data = {text:  'hello world'
}const handler = {// 监控data中的text属性变化set: function(target, prop, value){if(prop === 'text'){// 更新值target[prop] = value;// 更新试图paragraph.innerHTML = value;input.value = value;retur true;} else {return false;}}
}
// 构造 proxy 对象
const myText = new Proxy(data, handler);// 添加input 监听事件
input.addEventListener('input', function(e){myText.text = e.target.value; // 更新myText的值
});初始化值
myText.text = data.text;

#### Vue中如何在组件内部实现一个双向数据绑定?
假设有一个输入框组件,用户输入时,同步父组件页面中的数据。
具体思路:父组件通过props传值给子组件,子组件通过 $emit 来通知父组件修改相应的props值,具体实现如下:

import Vue from 'vue'
const component = {props: ['value'],template: ` < div > <input type = "text"@input = "handleInput": value = "value" > </div>`,data(){return{}},methods:{handleInput(e){this.$emit('input',e.target.value)}}
}new Vue({components:{CompOne:component},el:'#root',template:`<div><comp-one:value1="value"@input="value = arguments[0]"></comp - one > </div>`,data(){return{value:'123'}}
})

Vue中v-model的实现原理是怎样的?

当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新

Vue中如何监控某个属性值的变化?

比如现在需要监控data中, obj.a 的变化。Vue中监控对象属性的变化你可以这样:

watch: {obj: {handler(newValue, oldValue) {console.log('obj changed')},deep: true}
}

deep属性表示深层遍历,但是这么写会监控obj的所有属性变化,并不是我们想要的效果,所以做点修改:

watch: {'obj.a': {handler(newName, oldName) {console.log('obj.a changed')}}
}

还有一种方法,可以通过computed 来实现,只需要:

// 利用计算属性的特性来实现,当依赖改变时,便会重新计算一个新值。
computed: {a1() {return this.obj.a}
}

Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

<template><div><ul><li v-for="value in obj" :key="value">{{value}}</li></ul><button @click="addObjB">添加obj.b</button></div>
</template>
<script>export  default {data() {return {obj:{a:  'obj.a'}}},methods: {addObjB() {this.obj.b = 'obj.b'console.log(this.obj)}}}
</script>
<style>
</style>

点击button会发现, obj.b 已经成功添加,但是视图并未刷新:
image.png
image.png
原因在于在Vue实例创建时, obj.b 并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api—— $set():

// $set() 方法相当于手动的去把 obj.b 处理成一个响应式的属性,此时视图也会跟着改变了:
addObjB() {this.$set(this.obj, 'b', 'obj.b')console.log(this.obj)
}

视图改变:
image.png

delete和Vue.delete删除数组的区别

delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。
Vue.delete / this.$delete 直接删除了数组 改变了数组的键值。

var a = [1, 2, 3, 4]
var b = [1, 2, 3, 4]
delete a[1]
console.log(a)
this.$delete(b, 1)
console.log(b)

image.png
image.png

如何优化SPA应用的首屏加载速度慢的问题?

· 将公用的JS库通过script标签外部引入,减小 app.bundel 的大小,让浏览器并行下载资源文件,提高下载速度;
· 在配置 路由时,页面和组件使用懒加载的方式引入,进一步缩小 app.bundel 的体积,在调用某个组件时再加载对应的js文件;
· 加一个首屏loading图,提升用户体验;

前端如何优化网站性能?

1、减少 HTTP 请求数量
- css sprites
- 合并css和js文件,压缩
- 采用lazyLoad懒加载

2、控制资源文件加载优先级

3、利用浏览器缓存

4、减少重排(Reflow)
- 如果需要在DOM操作时添加样式,尽量使用增加class属性,而不是通过style操作样式。

5、减少 DOM 操作

6、图标使用 IconFont 替换

网页从输入网址到渲染完成经历了哪些过程?

  - 输入网址;- 发送到DNS服务器,并获取域名对应的web服务器对应的ip地址;- 与web服务器建立TCP连接;- 浏览器向web服务器发送http请求;- web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址);- 浏览器下载web服务器返回的数据及解析html源文件;- 生成DOM树,解析css和js,渲染页面,直至显示完成;

#Vue的生命周期

beforeCreate(创建前),在数据观测和初始化事件还未开始

created(创建后),完成数据观测,属性和方法的运算,初始化事件, $el 属性还没有显示出来

beforeMount(载入前),在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。

mounted(载入后),在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。

beforeUpdate(更新前),在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。

updated(更新后),在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

beforeDestroy(销毁前),在实例销毁之前调用。实例仍然完全可用。

destroyed(销毁后),在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

什么是vue生命周期?

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

vue生命周期的作用是什么?

它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

vue生命周期总共有几个阶段?

它可以总共分为8个阶段:创建前/后、载入前/后、更新前/后、销毁前/销毁后。

第一次页面加载会触发哪几个钩子?

beforeCreate、created、beforeMount、mounted 。

DOM 渲染在哪个周期中就已经完成?

mounted

Vue实现数据双向绑定的原理: Object.defineProperty()

1、首先Object.defineProperty()的用法:
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
语法:Object.defineProperty(obj, prop, descriptor)
obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptror:将被定义或修改的属性描述符。

2、vue实现数据双向绑定主要是:
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。

js通过Object.defineProperty()实现简单的双向绑定:

<body><div id="app"><input type="text" id="txt"><p id="show"></p></div>
</body>
<script type="text/javascript">var obj = {};Object.defineProperty(obj, 'txt', {get: function (){return obj},set: function (newValue) {document.getElementById('txt').value = newValue;document.getElementById('show').innerHTML = newValue}}) ;document.addEventListener('keyup', function (e) {obj.txt = e.target.value;});
</script>

js通过Observer、Compile、Watcher实现一个原生JS的双向绑定:

// 第一步 实现基本架构
// 第二步 把模型的数据 显示到视图
// 第三步  更新视图同步到模型,再更新视图
// 发布者
class Vue{constructor(options){this.options = options;this.$data = options.data;this.$el = document.querySelector(options,el);this._directives = {// 存放订阅者集合的数组对象  }this.Observer(this.$data);this.Compile(this.$el);}// 劫持数据Observer(data){// 更新视图  局部更新for(let key in data){this._driectives[key] = []; // 空类数组对象let val = data[key]; // 当前的值 let _this = this;Object.defineProperty(this.$data, key, {get: function(){return val;},set: function(newVal){if(newVal !== val){val = newVal;//_this._directives[key] 得到myText的数组_this._directives[key].forEach(watch=>{// 遍历订阅者的实例watch.update(); // 更新视图})}}});}}// 解析指令Compile(el){let nodes = el.children;] // 获取APP下面的子元素for(let i = 0;i < nodes.length; i++){let node = nodes[i]; // 当前元素if(node.children.length){// 如果当前元素含有子元素,就递归调用自己this.Compile(node);}if(node.hasAttribute('v-text')){// 获取属性值,对号加入对应的订阅者数组let attrVal = node.getAttribute("v-text")this._directives[attrVal].push(new Watcher(node, attrVal, this, 'innerHTML'));}if(node.hasAttribute('v-model')){let attrVal = node.getAttribute("v-model");this._directives[attrVal].push(new Watcher(node, attrVal, this, 'value'));// 监听文本框事件node.addEventListener('input', (function(){return function(){// console.log(node.value);// 更新视图到模型this.$data[attrVal] = node.value;}})());}}}class Watcher{constructor(el, vm, mySelf, attr){this.el = el; this.vm= vm; this.mySelf= mySelf; this.attr= attr; this.update(); // 初始化数据}update(){// div对象[innerHTML] = vue对象.data['myText']// input对象[value] = vue对象.data['myText']this.el[this.attr] = this.mySelf.$data[this.vm];}}
}

Vue组件间的参数传递

1、父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件: $emit 方法传递参数

2、非父子组件间的数据传递,兄弟组件传值
eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道)。

Vue的路由实现:hash模式 和 history模式

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。

history模式:history采用HTML5的新特性;且提供了两个新方法: pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。

Vue与Angular以及React的区别?

1、与AngularJS的区别

相同点:都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。

不同点:AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。

2、与React的区别

相同点:React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。

不同点:React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。

vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

beforeEach主要有3个参数to,from,next。
to:route即将进入的目标路由对象。
from:route当前导航正要离开的路由。
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

vuex是什么?怎么使用?哪种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。

在main.js引入store,注入。新建了一个目录store,… export 。

场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物image.png

state

Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。

mutations

mutations定义的方法动态修改Vuex 的 store 中的状态或数据。

getters

类似vue的计算属性,主要用来过滤一些数据。

action

actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count ++}},actions: {increment (context) {context.commit('increment');}}})

modules

项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}
const moduleB = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}
const moduleC = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}
const store = new Vuex.Store({modules: {a:  moduleA,b:  moduleB,c:  moduleC}
})

其他知识点:

css只在当前组件起作用

答:在style标签中写入scoped即可 例如:

v-if 和 v-show 区别

答:v-if按照条件是否渲染,v-show是display的block或none;

$route和 $router的区别

$ route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

http 和 https

HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议:
它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息,它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版。它是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压操作,并返回网络上传送回的结果。
HTTPS实际上应用了Netscape的安全套接字层(SSL)作为HTTP应用层的子层。(HTTPS使用端口443,而不是象HTTP那样使用端口80来和TCP/IP进行通信。)SSL使用40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。
HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。总的来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议要比http协议安全。

在URL前加https://前缀表明是用SSL(安全套接字)加密的,你的电脑与服务器之间收发的信息传输将更加安全。 Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定。

HTTPS和HTTP的区别:

https协议需要到ca申请证书,一般免费证书很少,需要交费。
http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的。
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。
详细参看:https://www.jianshu.com/p/6db0c6dc97a9

GET 和 POST

GET 和 POST 报文上的区别

先下结论,GET 和 POST 方法没有实质区别,只是报文格式不同。

GET 和 POST 只是 HTTP 协议中两种请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。

报文格式上,不带参数时,最大区别就是第一行方法名不同

POST方法请求报文第一行是这样的

POST /uri HTTP/1.1 \r\n

GET方法请求报文第一行是这样的

 GET /uri HTTP/1.1 \r\n

是的,不带参数时他们的区别就仅仅是报文的前几个字符不同而已

带参数时报文的区别呢? 在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中

举个例子,如果参数是 name=chengqm, age=22。
GET 方法简约版报文是这样的

GET /index.php?name=qiming.c&age=22 HTTP/1.1
Host:  localhost

POST 方法简约版报文是这样的

POST /index.php  HTTP/1.1
Host:  localhost
Content-Type:  application/x-www-form-urlencodedname=qiming.c&age=22

现在我们知道了两种方法本质上是 TCP 连接,没有差别,也就是说,如果我不按规范来也是可以的。我们可以在 URL 上写参数,然后方法使用 POST;也可以在 Body 写参数,然后方法使用 GET。当然,这需要服务端支持。

常见问题:

  1. GET 方法参数写法是固定的吗?
    在约定中,我们的参数是写在 ? 后面,用 & 分割。
    我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。
    也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,一种比较流行的写法是 http://www.example.com/user/name/chengqm/age/22。

  2. POST 方法比 GET 方法安全?
    按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。
    然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。
    要想安全传输,就只有加密,也就是 HTTPS。

  3. GET 方法的长度限制是怎么回事?
    HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。
    浏览器原因就不说了,服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。

  4. POST 方法会产生两个TCP数据包?
    HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。
    所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。

  5. w3school 里面说 URL 的最大长度是 2048 个字符
    url 长度限制是某些浏览器和服务器的限制,和 HTTP 协议没有关系。

#跨域 —— 9种跨域方式实现原理
参考:https://mp.weixin.qq.com/s/nkDkofBidKQFp5oG4-aJNg

什么是跨域?

当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。

同源策略

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。

同源策略限制内容有:

Cookie、LocalStorage、IndexedDB 等存储性内容
DOM 节点
AJAX 请求发送后,结果被浏览器拦截了

但是有三个标签是允许跨域加载资源:

<img src=XXX>
<link href=XXX>
<script src=XXX>

请求跨域了,那么请求到底发出去没有?

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

跨域解决方案:

(1)JSONP

(2)cors(后台设置:简单请求和复杂请求)

(3)postMeassage
HTML5 XMLHttpRequest Level 2 中的 API,windows属性,可用于解决:

  • 页面和其他打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

(4)websocket
实现了浏览器与服务器的全双工通信,websocket和http都是应用层协议,基于TCP协议,但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。

(5)node中间件代理(两次跨域)
借助了服务器和服务器之间无需遵循同源策略的特点。image.png

(6)nginx 反向代理
使用nginx反向代理实现跨域,是最简单的跨域方式。
支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。

实现思路:通过 nginx 配置一个代理服务器(域名与 domain1 相同,端口不同)做跳板机,反向代理访问 domain2 接口,并且可以顺便修改 cookie 中 domain 信息,方便当前域 cookie 写入,实现跨域登录。

//porxy服务器
server {listen  80;server_name  www.domain1.com;location  /  {proxy_pas  http://www.domain2.com:8080; #反向代理proxy_cookie_domain  www.domain2.com  www.domain1.com;  #修改cookie里域名index  index.html  index.htm;#当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*add_header Access-Control-Allow-Credentials true;}
}

最后通过命令行nginx -s reload启动 nginx

// index.html
var xhr = new XMLHttpRequest();
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();// server.js
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {var params = qs.parse(req.url.substring(2));// 向前台写cookieres.writeHead(200, {'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取});res.write(JSON.stringify(params));res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');

(7)window.name + iframe
window.name 属性的独特之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

其中 a.html 和 b.html 是同域的,都是http://localhost:3000;而 c.html 是http://localhost:4000

// a.html(http://localhost:3000/b.html)<iframe src="http://localhost:4000/c.html" frameborder="0" "load()" id="iframe"></iframe><script>let first = true// onload事件会触发2次,第1次加载跨域页,并留存数据于window.namefunction load() {if(first){// 第1次onload(跨域页)成功后,切换到同域代理页面let iframe = document.getElementById('iframe');iframe.src = 'http://localhost:3000/b.html';first = false;}else{// 第2次onload(同域b.html页)成功后,读取同域window.name中数据console.log(iframe.contentWindow.name);}}</script>

b.html 为中间代理页,与 a.html 同域,内容为空。

// c.html(http://localhost:4000/c.html)<script>window.name = '我不爱你'</script>

通过 iframe 的 src 属性由外域转向本地域,跨域数据即由 iframe 的 window.name 从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

(8)location.hash + iframe
实现原理: a.html 欲与 c.html 跨域相互通信,通过中间页 b.html 来实现。 三个页面,不同域之间利用 iframe 的 location.hash 传值,相同域之间直接 js 访问来通信。

具体实现步骤:一开始 a.html 给 c.html 传一个 hash 值,然后 c.html 收到 hash 值后,再把 hash 值传递给 b.html,最后 b.html 将结果放到 a.html 的 hash 值中。
同样的,a.html 和 b.html 是同域的,都是http://localhost:3000;而 c.html 是http://localhost:4000

// a.html<iframe src="http://localhost:4000/c.html#iloveyou"></iframe><script>window.onhashchange = function () { //检测hash的变化console.log(location.hash);}</script>// b.html<script>window.parent.parent.location.hash = location.hash//b.html将结果放到a.html的hash值中,b.html可通过parent.parent访问a.html页面</script>// c.htmlconsole.log(location.hash);let iframe = document.createElement('iframe');iframe.src = 'http://localhost:3000/b.html#idontloveyou';document.body.appendChild(iframe);

(9)document.domain + iframe
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
只需要给页面添加 document.domain =‘test.com’ 表示二级域名都相同就可以实现跨域。

实现原理:两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。

我们看个例子:页面a.zf1.cn:3000/a.html获取页面b.zf1.cn:3000/b.html中 a 的值

// a.html
<body>helloa<iframe src="http://b.zf1.cn:3000/b.html" frameborder="0" "load()" id="frame"></iframe><script>document.domain = 'zf1.cn'function load() {console.log(frame.contentWindow.a);}</script>
</body>
// b.html
<body>hellob<script>document.domain = 'zf1.cn'var a = 100;</script>
</body>

总结:

  • CORS 支持所有类型的 HTTP 请求,是跨域 HTTP 请求的根本解决方案
  • JSONP 只支持 GET 请求,JSONP 的优势在于支持老式浏览器,以及可以向不支持 CORS 的网站请求数据。
  • 不管是 Node 中间件代理还是 nginx 反向代理,主要是通过同源策略对服务器不加限制。
  • 日常工作中,用得比较多的跨域方案是 cors 和 nginx 反向代理

PWA

PWA全称Progressive Web App,即 渐进式WEB应用。

一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能

解决了哪些问题?
可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏
实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能
实现了消息推送
它解决了上述提到的问题,这些特性将使得 Web 应用渐进式接近原生 App。
更多可参看:https://segmentfault.com/a/1190000012353473?utm_source=tag-newest

原型与原型链

什么是原型?

在js中,所有对象都是Object的实例,并集成Object.prototype的属性和方法,但是有一些是隐性的。

所有引用类型都具有对象特性,可以自由扩展属性。

var obj = {};
obj.attribute = "new attr";
var arr = [];
arr.attribute = "new attr";
function fn () {}
fn.attribute = "new attr";

所有的引用类型(包括数组,对象,函数)都有隐性原型属性(proto), 值也是一个普通的对象。

console.log(obj.__proto__);

所有的函数,都有一个 prototype 属性,值也是一个普通的对象。

console.log(obj.prototype);

所有的引用类型的proto属性值都指向构造函数的 prototype 属性值。

console.log(obj.__proto__ === Object.prototype); // true

当试图获取对象属性时,如果对象本身没有这个属性,那就会去他的proto(prototype)中去寻找。

function Dog(name){ this.name = name; 
} 
Dog.prototype.callName = function (){ console.log(this.name,"wang wang"); 
}
let dog1 = new Dog("Three Mountain"); 
dog1.printName = function (){ console.log(this.name);
}
dog1.callName();  // Three Mountain wang wang
dog1.printName(); // Three Mountain

原型链图:image.png

作用域及闭包

只有函数才能创造作用域。
for if else 不能创造作用域。

this:

本质上来说,在 js 里 this 是一个指向函数执行环境的指针。this 永远指向最后调用它的对象,并且在执行时才能获取值,定义是无法确认他的值。

var a = { name : "A", fn : function (){console.log (this.name) } 
} 
a.fn() // this === a 
a 调用了fn() 所以此时this为a
a.fn.call ({name : "B"}) // this === {name : "B"} 
使用call(),将this的值指定为{name:"B"}
var fn1 = a.fn 
fn1() // this === window
虽然指定fn1 = a.fn,但是调用是有window调用,所以this 为window

this 有多种使用场景:

  1. 作为构造函数执行:
function  Student(name,age) {this.name = name           // this === sthis.age = age             // this === s//return  this
}
var s = new Student("py1988",30)
  1. 作为普通函数执行:
function  fn () {console.log (this)       // this === window
}
fn ();
  1. 作为对象属性执行:
var obj = {name : "A",printName : function () {console.log (this.name)  // this === obj}
}
obj.printName ()
  1. call(), apply(), bind(): 这是重点!
    三个函数都可以修改this的指向:
var name = "小明" , age = "17" 
var obj = { name : "安妮", objAge :this.age, fun : function (like,dislike) { console.log (this.name + "今年" + this.age ,"喜欢吃" + like + "不喜欢吃" + dislike) ;} } 
var a = { name : "Jay", age : 23 } 
obj.fun.call(a,"苹果","香蕉") // Jay今年23 喜欢吃苹果不喜欢吃香蕉 
obj.fun.apply(a,["苹果","香蕉"]) // Jay今年23 喜欢吃苹果不喜欢吃香蕉 
obj.fun.bind(a,"苹果","香蕉")() // Jay今年23 喜欢吃苹果不喜欢吃香蕉

首先 call,apply,bind 第一个参数都是 this 指向的对象,call 和 apply 如果第一个参数指向 null 或 undefined 时,那么 this 会指向 windows 对象。

call,apply,bind 的执行方式如上例所示。call,apply 都是改变上下文中的 this,并且是立即执行的。bind 方法可以让对应的函数想什么时候调用就什么时候调用。

闭包:

闭包的概念很抽象,看下面的例子你就会理解什么叫闭包了:

function a(){var n = 0;this.fun = function () {n++; console.log(n);};
}
var c = new a();
c.fun();  //1
c.fun();  //2

闭包就是能够读取其他函数内部变量的函数。在 js 中只有函数内部的子函数才能读取局部变量。所以可以简单的理解为:定义在内部函数的函数。

异步和单线程

我们先感受下异步。

console.log("start");
setTimeout(function () {console.log("medium");
}, 1000);
console.log("end");

使用异步后,打印的顺序为 start-> end->medium。因为没有阻塞。

为什么会产生异步呢?

首先因为 js 为单线程,也就是说 CPU 同一时间只能处理一个事务。得按顺序,一个一个处理。

如上例所示,第一步:执行第一行打印 “start”;第二步:执行 setTimeout,将其中的函数分存起来,等待时间结束后执行;第三步:执行最后一行,打印 “end”;第四部:处于空闲状态,查看暂存中,是否有可执行的函数;第五步:执行分存函数。

为什么 js 引擎是单线程?

js 的主要用途是与用户互动,以及操作 DOM,这决定它只能是单线程。例:一个线程要添加 DOM 节点,一个线程要删减 DOM 节点,容易造成分歧。

为了更好使用多 CPU,H5 提供了 web Worker 标准,允许 js 创建多线程,但是子线程受到主线程控制,而且不得操作 DOM。

任务列队

单线程就意味着,所有的任务都要排队,前一个结束,才会执行后面的任务。如果列队是因为计算量大,CPU 忙不过来,倒也算了。但是更多的时候,CPU 是闲置的,因为 IO 设备处理得很慢,例如 ajax 读取网络数据。js 设计者便想到,主线程完全可以不管 IO 设备,将其挂起,然后执行后面的任务。等后面的任务结束掉,在反过头来处理挂起的任务。

好,我们来梳理一下:

1)所有的同步任务都在主线程上执行,行程一个执行栈。

2)除了主线程之外,还存在一个任务列队,只要一步任务有了运行结果,就在任务列队中植入一个时间。

3)主线程完成所有任务,就会读取列队任务,并将其执行。

4)重复上面三步。

只要主线程空了,就会读取任务列队,这就是 js 的运行机制,也被称为 event loop(事件循环)。

ES6 语法

ES6,强制开启严格模式!

let 和 const

作用域的概念:
全局作用域,函数作用域,块作用域
<暂时性死区>

let和const不能重复定义;const声明时必须赋值,let 不必须;

解构赋值

解构赋值的分类:
数组解构赋值,对象解构赋值,字符串解构赋值,
布尔值解构赋值,函数参数解构赋值,数值解构赋值

使用场景:

数组结构赋值:

(1)默认值:

  function fn(a, b=2){...}

(2)变量交换

{let a = 1;let b = 2;[a, b] = [b, a];console.log(a,  b);
}

(3)获取函数返回值

{function  f(){return [1,2,3,4];}let a,  b,  c,  d;[a,  b,c,d] = f();  //  接收所有值[a, , , b] = f();  // 接收指定值[a, ...b] = f(); //  分开接收
}

对象解构赋值:

{let o = {p:42,  q:true}let {p,q} = o;console.log(p,q);
}

(1)默认值:

{let {a = 5, b = 10} = {a : 3}console.log(a,b) // 3, 5
}

(2)json对象取值 :特别常用的场景!

{let data = {title: 'abc',test: [{title:  'test',desc:  '描述'}]}// 声明一个跟解构对象格式一致的对象,来接收对象中的值let {title : esTitle,  test: [{title: cnTitle}]} = data;console.log(esTitle,  cnTitle);
}

正则扩展:

构造函数的变化、正则方法扩展、u修饰符、y修饰符、s修饰符

es5中有一下两种正则表达式写法:

{// 两个参数的情况,前面是匹配字符串let regex = new RegExp('xyz', 'i');// 一个参数的情况,前面是正则表达式let regex2 = new RegExp(/xyz/i); 
}

es6中,允许前面是正则表达式,而后面跟着修饰符的两个参数的写法:

{let regex3 = new RegExp(/xyz/ig, 'i'); // 但这种写法后面的修饰符会覆盖正则中的修饰符//  flags是es6中正则表达式的新的API,输出的结果是正则表达式的修饰符console.log(regex3.flags);  //  输出的是 ' i '
}

y修饰符:

{let s = 'bbb_bb_b';let a1 = /b+/g;let a2 = /b+/y;console.log('one', a1.exec(s), a2.exec(s));console.log('two', a1.exec(s), a2.exec(s));
}

g和y修饰符的共同点:都是全局匹配
不同点:
g:可以不连续匹配,bbb_bb_b
y: 粘连模式,必须连续匹配b后面如果不是b了,就不会继续匹配
sticky可以查看是否开启了粘连模式:a1.sticky

u修饰符:

u修饰符,可以识别大于2个字节的字符;
es5中,. 能匹配任何字符,但是前提是小于两个字节的
s修饰符:es6中还未实现

字符串扩展:(要安装babel-polyfill)

处理unicode编码大于0xffff的字符 => 用{}包裹起来
`\u20BB7` => `\u{20BB7}`
es5中:
获取unicode编码对应的字符:fromCharCode()
获取字符对应的unicode编码:charCodeAt();

es6中:
获取unicode编码对应的字符:fromCharPoint();
获取字符对应的unicode编码:codePointAt(); // 能获取超过0xFFFF长度的编码,并正确显示

es6中有一个字符串遍历器接口,可以正确处理unicode编码大于0xFFFF的字符串

{let str = '/u{20BB7}abc';for(let code of str){console.log('es6', code);}//let  of 可以正确遍历出0xFFFF编码长度的字符串对应的字符,不会出现乱码
}

str.includes('x'):判断字符串中是否包含了某个字符
str.startsWith('x'):判断字符串是不是已某个字符开始的
str.endsWith('x'):判断字符串是不是已某个字符结束的
str.repeat(2):重复字符串

模板字符串(很重要):

`你好,${name},欢迎你!`

padStart 和 padEnd (这两个是ES7的草案,需要babel-polyfill)

console.log('1'.padStart(2,  '0')); //  '01'
console.log('1'.padEnd(2,  '0')); //  '10'

标签模板:

1.怎么用?

{let user = {name:   'list',info:  'hello world'};console.log(abc`i am ${user.name}, ${user.info}`);function abc(s,  v1,  v2){console.log(s,  v1,  v2);return s+v1+v2;}
}

2.在哪里用?
防止XSS攻击,和处理多语言转换的时候用

string.raw:可以将所有的 ’ \ ’ 进行了转义,即在前面又加了一个
String.raw`Hi\n${1+2}` // Hi\n3

数值扩展:

Number.isFinite() :判断一个值是否有尽
Number.isNaN() :判断一个数是不是NaN
Number.isInteger() :判断是不是整数 2.0也是true

Number.MAX_SAFE_INTEGER // 最大安全数值
Number.MIN_SAFE_INTEGER // 最小安全数值

Number.isSafeInteger() // 判断一个数字是不是在安全数的范围内:
Math.trunc(4.1); //4 // 取小数的整数部分
Math.sign() // 结果只有-1, 0 ,1, NaN // 判断是正数,负数,还是零
Math.cbrt(8); // 2 // 计算立方根

还有三角函数方法,对数方法,都是es6新增的

数组扩展:

Array.from
Array.of
copyWithin
find \ findIndex
fill
entries \ keys \ values
includes

函数扩展:

1、参数默认值

{function test(x, y = " 23 "){console.log(x,  y);}test(2) // 2  23
}
//  要注意默认值后面不能再有没有默认值的参数变量
//  这就是错误的function test(x, y = " 23 " , c)  ...

关于取值作用域的问题:

{let x = 'test';function test(x, y=x){console.log(x,y);}test('kill'); //  kill kill
}

2、rest参数
把一系列的参数都转换为数组,在你不确定有多少个参数的时候
注意,rest参数后面不能再有其他的参数

{function test( ...arg ){for (let v of arg){console.log(v);}}test(1,2,3,4); // 1 2 3 4
}

3、扩展运算符
扩展运算符和rest运算符是一个相反的作用
它的作用是:把一个数组拆成离散的值

{console.log(...[1,2,3]); // 1  2  3console.log('a', ...[1,2,3]) //  'a'  1  2  3
}

4、箭头函数

{let arrow = v => v*2;//  等同于function arrow(v){return v*2;}// 无参数let arrow = () => v*3;//  等同于function arrow(){return v*3;}
}

5、this绑定
因为this在指向在箭头函数和普通函数不一样,所以要考虑什么时候适合用箭头函数,什么时候不适合用箭头函数;
this在普通函数中,指向函数被调用时的对象所在;
this在箭头函数中,指向函数被定义时的对象所在;
6、尾调用
区分特征:函数的最后一句话是不是函数

{function tail(x){console.log('tail',  x);}function fx(x){return tail(x);}fx(123);
}
//  尾调用的用处:提升(递归函数,嵌套函数)性能

对象(object)扩展:

1、简介表示法:

{let o = 1;let k = 2;//  es5中声明一个对象let es5 = {o:  o,k:  k};//  es6中,如果键值相同,可以这样写:let es6 = {o,k};//  如果对象里面有方法:let es5_method = {hello: function(){}};let es6_method = {hello(){}}
}

2、属性表达式:

{let a = 'b';let es5_obj = {a: 'c',b: 'c'};// 对象的key值,可以是一个表达式,这叫做属性表达式//  这里的 [a] = 'b';let es6_obj = {[a]:  'c'}console.log(es5_obj,  es6_obj);
}

3、扩展运算符:
babel对它的支持不是很好,加了babel-polyfill还是会报错

{let {a, b, ...c} = {a: 'test', b:'re', c:'ccc', d:'ddd'};解析过后c的值应该是:c: {c:'ccc',d:'ddd'}
}

4、Object新增方法:

  //  新增APIObject.is() 的功能和 ‘===’ 没有区别,判断两个值是否相等Object.is(str, str); //判断两个字符串是否相等//  要注意,数组和对象是引用类型,虽然都是空数组,但是引用的地址不同,所以:object.is([],[])  // 结果是falseObject.assign() : 浅拷贝//  拷贝的是引用地址,不是值;//  只拷贝自身的属性,不会拷贝继承的属性,和不可枚举的属性Object.assign({a:''a}, {b:'b'}); // {a: 'a', b: 'b'}Object.entries() : 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致区别在于 for-in 循环也枚举原型链中的属性const object1 = { foo: 'bar', baz: 42 };console.log(Object.entries(object1)[1]);// expected output: Array ["baz", 42]const object2 = { 0: 'a', 1: 'b', 2: 'c' };console.log(Object.entries(object2)[2]);// expected output: Array ["2", "c"]const result = Object.entries(object2).sort((a, b) => a - b);console.log(Object.entries(result)[1]);// expected output: Array ["1", Array ["1", "b"]]

Symbol:

1、Symbol的概念:
Symbol可提供一个独一无二的值

let a1 = Symbol();
let a2 = Symbol();
console.log(a1 === a2); // false// 定义了以后,将来要取回来,就用这种方式
let a3 = Symbol.for('a3'); // for中的a3是一个key值,如果在全局注册过,就返回这个值,如果没有注册过,就注册一个独一无二的值let a4 = Symbol.for('a3');
let a5 = Symbol.for('a3');
console.log(a4 === a5); // true

2、Symbol的作用:

{let a1 = Symbol.for('abc');let obj = {[a1] : '123','abc' : 234,'c' : 456}console.log('obj', obj); // {Symbol(abc): '123', 'abc': 234, 'c': 456}

要注意一点:用Symbol做key值,通过for...inlet...of是拿不到key值的

  for(let [key, value] of Object.entries(obj)){console.log(key, value) ; //拿不到Symbol(abc)和其值}

这时可以通过Object.getOwnPropertySymbols()拿到Symbol定义的值,但是它拿不到其他的值

  Object.getOwnPropertySymbols(obj).forEach(function(item){console.log(obj[item]); // 123})

如果想拿到所有的值,可以通过Reflect.ownKeys()拿到

  Reflect.ownKeys(obj).forEach(function(item){console.log('ownKeys', item, obj[item])})

ES6数据结构:

Set:

1、类似数组,但集合中的元素不能重复

{let list = new Set();list.add(5); // 添加list.add(7);list.size // 获取set中的长度(个数)// 初始化set中的值let arr = [1,2,3,4,5];let list1 = new Set(arr);// 不可重复性let list2 = new Set();list2.add(1);list2.add(2);list2.add(1);console.log(list2); // 不会打印出后面重复的元素,也不会报错,这可以用于去重这里要注意,Set不会做数据类型的转换,即 2 和 '2' 在set看来是不一样的

2、Set实例的几个方法和属性值:
add():添加某个元素
delete():删除某个元素
clear():清空所有元素
has():判断有没有某个元素,返回布尔类型
size:返回集合中元素的个数

3、Set实例的遍历:

// for...of
for(let key of list.keys()){console.log('keys', key);
}
for(let value of list.values()){console.log('value', value);
}
for(let value of list){console.log('value', value);
}
for(let [key,  value] of list.entries()){console.log('entries', key, value);
}
key和value的值一样,都是元素的名称;
不加.key或者.values,也是可以的

Map

1 、类似Object,key可以是任意类型(object中key只能是字符串)

{let map = new Map();let arr = ['123'];map.set(arr, 456); // Map可以用数组作为key(或其他任意类型)哦~console.log('map', map, map.get(arr));// 结果:map  Map{["123"] => 456}  456// 初始化Map中的值let map1 = new Map([['a', 123], ['b', 456]]);  // 一定要注意这种格式
}

2、Map实例的几个方法和属性值:
get():获取某个元素
set():添加某个元素
delete():删除某个元素
clear():清空所有元素
has():判断有没有某个元素,返回布尔类型
size:返回集合中元素的个数

3、Map 结构转为数组结构
比较快速的方法是结合使用扩展运算符(…)

let map = new Map([[1, 'one'],[2, 'two'],[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]

4、Map 循环遍历
Map 原生提供三个遍历器:
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。

let map = new Map([['F', 'no'],['T', 'yes'],
]);for (let key of map.keys()) {console.log(key);
}
// "F"
// "T"for (let value of map.values()) {console.log(value);
}
// "no"
// "yes"for (let item of map.entries()) {console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"// 或者
for (let [key, value] of map.entries()) {console.log(key, value);
}// 等同于使用map.entries()
// 这个例子可以看出:Map 结构的默认遍历器接口(Symbol.iterator 属性),就是 entries 方法。
for (let [key, value] of map) {console.log(key, value);
}

5、Map 获取第一个元素

const m = new Map();
m.set('key1', {})
m.set('keyN', {})console.log(m.entries().next().value); // [ 'key1', {} ]// 获取第一个key
console.log(m.keys().next().value); // key1// 获取第一个value
console.log(m.values().next().value); // {}

Map与Array的对比 、 Set与Array的对比

数据结构横向对比,增、查、改、删

// Map与Array
let map = new Map();
let array = [];// 增
map.set('t',  1);
array.push({t:1});
console.info('may-array', map,  array);// 查
let map_exist = map.has('t');
let array_exist = array.find(item=>item.t);
console.info('may-array',  map_exist, array_exist); //map返回的是布尔值,数组返回的是这个值// 改
map.set('t',  2);
array.forEach(item => item.t ? item.t = 2 : ' '); // 先要判断是否存在,才执行
console.info('may-array-modify',  map, array); // 删
map.delete('t');
let index = array.findIndex(item => item.t); // 查找每一个元素中带t的元素
array.splice(index, 1);
console.info('may-array-del', map, array); // Set与Array
let map = new Set();
let array = [];// 增
set.add({t :1});
array.push({t:1});
console.info('set-array', set,  array);// 查
let set_exist = set.has({t:1}); //这里应该是填入保存的地址,这样写会报错 
let array_exist = array.find(item=>item.t);
console.info('may-array',  set_exist, array_exist); //set返回的是布尔值,数组返回的是这个值// 改
set.forEach(item => item.t ? item.t = 2: ' ');
array.forEach(item => item.t ? item.t = 2 : ' '); // 先要判断是否存在,才执行
console.info('may-array-modify',  set, array); // 删
set.forEach(item => item.t ? set.delete(item) : ' ');
let index = array.findIndex(item => item.t); // 查找每一个元素中带t的元素
array.splice(index, 1);
console.info('may-array-del', set, array); 

Proxy和Reflect

Proxy:可以用来代理对对象的访问
Reflect 的方法和用法和Proxy一模一样。只是使用方式不一样,Proxy需要new,而Reflect直接使用(Reflect.get())

// Proxy的几个常用方法:
// 其中target为代理对象参数,原本obj的属性,它都有,实际传入的代理对象,是proxy的实例化对象// 获取对象属性
get(target, key){}// 设置对象属性
set(target, key, value){}// 判断对象是否有某个属性,可以拦截判断,欺骗访问
has(target, key){}// 删除对象属性:拦截delete,如果不想用户删除对象中的某些属性
deleteProperty(target, key){}// 拦截Object.keys, Object.getOwnPropertySymbols, Object.getOwnPropertyNames
ownKeys(){}

完整示例,及Proxy在开发中的使用:

{let obj = {time: '2017-03-11',name: 'net',_r: 123}let monitor = new Proxy(obj, {// 拦截对象属性的读取get(target, key) {return target[key].replace('2017', '2018')},// 拦截对象设置属性set(target, key, value) {if (key === 'name') {return (target[key] = value)} else {return target[key]}},// 拦截key in object操作has(target, key) {if (key === 'name') {return target[key]} else {return false}},// 拦截deletedeleteProperty(target, key) {if (key.indexOf('_') > -1) {delete target[key]return true} else {return target[key]}},// 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNamesownKeys(target) {return Object.keys(target).filter(item => item != 'time')}})console.log('get', monitor.time)monitor.time = '2018'monitor.name = 'mukewang'console.log('set', monitor.time, monitor)console.log('has', 'name' in monitor, 'time' in monitor)// delete monitor.time;// console.log('delete',monitor);//// delete monitor._r;// console.log('delete',monitor);console.log('ownKeys', Object.keys(monitor))
}{let obj = {time: '2017-03-11',name: 'net',_r: 123}console.log('Reflect get', Reflect.get(obj, 'time'))Reflect.set(obj, 'name', 'mukewang')console.log(obj)console.log('has', Reflect.has(obj, 'name'))
}// proxy常用的情景:对数据类型进行校验,实现与业务解耦
{function validator(target, validator) {return new Proxy(target, {_validator: validator,set(target, key, value, proxy) {// 判断是否有对应可操作的属性if (target.hasOwnProperty(key)) {let va = this._validator[key]if (!!va(value)) {// 如果所访问的属性有值,则执行代理操作(这里仅以Set为例),将代理返回到真实对象proxyreturn Reflect.set(target, key, value, proxy)} else {throw Error(`不能设置${key}到${value}`)}} else {// 如果没有,则抛出异常throw Error(`${key} 不存在`)}}})}// 模拟一个条件类const personValidators = {name(val) {return typeof val === 'string'},age(val) {return typeof val === 'number' && val > 18},mobile(val) {}}// 模拟一个被代理的类class Person {constructor(name, age) {this.name = namethis.age = agethis.mobile = '1111'// 这里的this,指的是Person的实例化对象// Person类返回一个validator方法,validator方法返回一个proxy代理,//也就是说访问Person的实例,会经过validator中的proxy代理,进行筛选过滤return validator(this, personValidators)}}// 实例化Person类const person = new Person('lilei', 30)console.info(person)person.name = 'Han mei mei'console.info(person)
}

ES6中的 类和对象

基本语法 | 类的继承 | 静态方法 | 静态属性 | getter | setter

1、基本定义和生成实例

 class Parent{// 定义类中的构造函数constructor(name = 'zk'){this.name = name;}
}let v_parent = new Parent('z');
console.log('构造函数实例', v_parent)

2、类的继承
定义一个父类,子类来继承

class parent{constructor(name='zk'){this.name = name;}
}class child extends parent{// 继承父类的子类,可以覆盖 / 把实际需要的参数传递给 父类的参数constructor(name = 'child'){super(name); //要覆盖父类哪个参数,就传递哪个参数名;如果不传,则默认全部使用父类参数的默认值// 如果子类还要增加自己的属性,一定要放在super之后this.type = 'child';}
}console.log('继承', new Child('hello'));

getter 和 setter

class Parent{constructor(name = 'zk'){this.name = name;    }// getter// 注意,get后面的是属性,不是方法!get longName(){return 'mk' + this.name}// setterset longName(value){this.name = value}
}// get操作
let v = new Parent();
console.log('getter',v.longName);
// set操作
v.longName = 'hello'
console.log('setter',v.longName);

静态方法 的定义和使用

// static只是用来定义静态方法,不是用来定义静态属性用的!
// 静态属性是直接在类上定义的。
class Parent{constructor(name = 'zk'){this.name = name;}static tell(){console.log('tell')}
}Parent.tell();  // tell

静态属性的定义和使用(静态属性没有关键词(暂时没有,虽然有提案))

class Parent{constructor(name = 'zk'){this.name = name;}static tell(){console.log('tell')}
}Parent.type = 'type'; // 直接在类上定义属性,不用new实例
console.log('静态属性', Parent.type);

思考:什么样的场景下适合用静态方法,什么样的场景下适合用静态属性?

Promise

什么是异步 | Promise的作用 |  Promise的基本用法

现在的js异步编程的方式有一下几种:
1.回调函数 2.事件监听 3.发布/订阅 4.Promise 对象 5.Generator

之前有两种方式:通过回调函数、通过触发方法
而现在的Promise更适合异步操作

// 通过模拟ajax请求,来使用promise实现异步操作
{let ajax = function(){console.log('执行1');return new Promise(function(resolve, reject){setTimeout(function(){resolve()}, 1000)                            })}ajax().then(function(){console.log("然后执行2");})
}

如果是多个异步操作呢?

// 在then()中继续使用promise即可
{let ajax=function(){console.log('执行3');return new Promise(function(resolve, reject){setTimeout(function () {resolve()}, 1000);})};ajax().then(function(){return new Promise(function(resolve, reject){setTimeout(function () {resolve()}, 2000);});}).then(function(){console.log('timeout3');})
}

Promise 提供 then 方法加载回调函数,catch方法捕捉执行过程中抛出的错误。catch捕获出错信息,err就是具体的出错信息

{let ajax=function(num){console.log('执行4');return new Promise(function(resolve,reject){if(num>5){resolve()}else{throw new Error('出错了')}})}ajax(6).then(function(){console.log('log',6);}).catch(function(err){console.log('catch',err);});ajax(3).then(function(){console.log('log',3);}).catch(function(err){console.log('catch',err);});
}

promise的高级用法

promise.all promise.race(赛跑)

情景1:保证所有图片都加载完成,再显示页面

  {// 所有图片加载完再添加到页面function loadImg(src){return new Promise((resolve,reject)=>{let img=document.createElement('img');img.src=src;img.function(){resolve(img);}img.function(err){reject(err);}})}function showImgs(imgs){imgs.forEach(function(img){document.body.appendChild(img);})}Promise.all([loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')]).then(showImgs)}

情景2:同一个资源有多个来源,只要一个来源请求成功,就添加到页面,其他的忽略不管(先到先得)

{// 有一个图片加载完就添加到页面function loadImg(src){return new Promise((resolve,reject)=>{let img=document.createElement('img');img.src=src;img.function(){resolve(img);}img.function(err){reject(err);}})}function showImgs(img){let p=document.createElement('p');p.appendChild(img);document.body.appendChild(p)}Promise.race([loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')]).then(showImgs)}

Iterator 和 for…of 循环

什么是Iterator接口 | Iterator的基本用法 | for...of 循环

for…of只能遍历数组,如果其他数据格式也想通过for…of来遍历,前提条件是它本身自带Iterator接口,如果没有,则需要为其自定义Iterator接口

数组支持遍历,因为它本身已经封装好了Iterator接口:

// arr本身有一个Iterator的方法,通过arr[Symbol.iterator]()可以触发,这个方法会返回一个对象,对象有一个next()方法,用来输出每次遍历的结果
{let arr=['hello','world'];let map=arr[Symbol.iterator]();console.log(map.next());console.log(map.next());console.log(map.next());结果:Object{value: 'hello', done: false}Object{value: 'world', done: false}Object{value: undefined, done: true}
}

如果其他没有Iterator接口的数据类型,也想实现遍历,则可以自定义Iterator接口

{let obj={start:[1,3,2],end:[7,9,8],[Symbol.iterator](){let self=this;let index=0;let arr=self.start.concat(self.end);let len=arr.length;return {// 注意:这里要返回一个对象,对象中包含next()方法,而且返回值有两个,value和donenext(){if(index<len){return {// 注意每遍历一次,index都要+1value:arr[index++],done:false}}else{return {value:arr[index++],done:true}}}}}}// 本身for...of只能用来遍历数组,但通过为obj自定义了Iterator接口,从而使for...of也可以遍历objfor(let key of obj){console.log(key);}
}

说到for…of,就来回顾一下js中,数据的操作方法 和 几个循环的区别:

数组的操作方法:
会改变原数组的有:pop push unshift shift splice reverse sort
不会改变原数组的有:indexOf lastIndexof concat slice

其他常用操作方法:
es5的有:forEach filter map some every reduce
es6的有:find includes

几个循环方法及其区别:
forEach、for、for...in、for..of

1、for (编程式)

let arr = [1,2,3,4,5];
for(let i = 0;i<arr.length;i++){console.log(arr[i]);
}

2、forEach (声明式:不关心如何实现)

// 不支持return,它会遍历到结束
let arr = [1,2,3,4,5];
arr.forEach(function(item){console.log(item);
})

3、for…in (平时不用)

支持return,但一般不用它遍历数组
1- 因为索引不是数字,是字符串;
2- 因为for...in还会遍历出数组的私有属性,会影响length的准确性
let arr = [1,2,3,4,5];
arr.b = '100';
for(let key in arr){// key会变成字符串类型console.log(key) // 会把私有属性b也遍历出来
}

4、for…of (es6语法)

// 用于遍历数组
// 既可以return,又不会遍历出私有属性
let arr = [1,2,3,4,5];
for(let value of arr){console.log(value);
}// 如果想让for...of遍历对象,不仅可以通过Iterator添加接口的方式,也可以通过Object.keys()来变通实现
let obj = {school: 'zk',age: 9
}
for(let value of Object.keys(obj)){console.log(obj[value])
}

filter的用法:

是否操作原数组:不操作
返回结果:过滤后的新数组
回调函数返回结果:如果返回true,则将这一项放入新数组中

// 如果想筛选(删除)某些项,可以用filter
{let arr = [1,2,3,4,5];let newArr = arr.filter(function(item){return item>2 && item<5;});console.log(newArr); // [3,4]
}

map(映射)的用法:

将原有的数组映射成一个新的数组

是否操作原数组:不操作
返回结果:映射后的新数组
回调函数返回结果:回调函数中返回什么,这一项就是什么

// 可以用于将json返回值,拼接成dom元素,即更新某些项,可以用map
{let arr1 = [1,2,3];let newArr1 = arr1.map(function(item){return `<li>${item}</li>`});console.log(newArr1.join('')); // <li>1</li><li>2</li><li>3</li>
}

includes的用法:

看数组中是否包含某个值

是否操作原数组:不操作
返回结果:判断结果布尔值
回调函数返回结果:包含则返回true,否则返回false

{let arr3 = [1,2,3,4,5,6];console.log(arr3.includes(5));
}

find的用法:

找到数组中的某个值

是否操作原数组:不操作
返回结果:判断找到的值
回调函数返回结果:回调中返回true,表示找到了,找到后即停止遍历;找不到返回undefined

{let arr4 = [1,2,3,4,5,55,6];let result = arr4.find(function(item, index){return item.toString().indexOf(5) > -1})console.log(result);
}

some的用法:

找到true后停止,返回true ;类似 “或”

是否操作原数组:不操作
返回结果:判断数组中是否存在某值符合条件
回调函数返回结果:判断有一个条件成立(或存在某值),就返回true,并立即停止

{let arr4 = [1,2,3,4,5];let result = arr4.some(function(item, index){return item.toString().indexOf(5) > -1})console.log(result);
}

every的用法:

找到false后停止,返回false;类似 “与”

是否操作原数组:不操作
返回结果:判断数组中是否所有的值都符合条件
回调函数返回结果:判断一旦有一个条件不符合(或不存在某值),就返回false,并立即停止

{let arr4 = [1,2,3,4,5,55,6];let result = arr4.every(function(item, index){return item.toString().indexOf(5) > -1})console.log(result);
}

reduce(翻译:收敛,使还原,使变弱)

有四个参数(prev, next, index, item)
用法:将上一次的结果作为下一次的第一个,继续和后面的数据进行操作
即1和2的结果,与3操作,他们的结果再与4操作,以此类推

是否操作原数组:不操作
返回结果:返回叠加后的结果
回调函数返回结果:返回回调函数返回的结果
`

{let arr4 = [1,2,3,4,5];//第一次 prev:代表数组的前一项;next:代表数组的第二项//第二次 prev:是数组的上一次返回值;next:是数组的第三项//如果没有返回值,则第二次的prev便是undefinedlet reduce = arr4.reduce(function(prev, next, index, item){// item为原数组console.log(arguments);// return 100;})console.log(reduce );
}

应用举例:

1、计算多个商品的单价和数量的价格总和;
2、将二维数组,变成一维数组;

// 应用1:
let sum2 = [{price:30,count:2},{price:30,count:3},{price:30,count:4} ].reduce(function(prev, next){console.log(prev, next)return prev+next.price*next.count 
}, 0); // 这个0,是默认执行第一次的prev(即默认第一项的值)// reduce有两个参数:第一个是方法,第二个是默认第一项
// 应用2:
let arrs = [[1,2,3],[4,5,6],[7,8,9]];
let flat = arrs.reduce(function(prev,next){return prev.concat(next);
});
console.log(flat); // [1,2,3,4,5,6,7,8,9] 

Generator(发生器)

异步编程解决方案(相对promise更高级)
基本概念 | next函数的用法 | yield*的用法

Generator是什么?

举例来说,读取文件的协程写法如下。

functionasnycJob(){// ...其他代码var f=yield readFile( fileA);// ...其他代码
}

上面代码的函数 asyncJob 是一个协程,它的奥妙就在其中的 yield 命令。它表示执行到此处,执行权将交给其他协程。也就是说,yield命令是异步两个阶段的分界线。

协程遇到 yield 命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。它的最大优点,就是代码的写法非常像同步操作,如果去除yield命令,简直一模一样。

以上举例转载自:https://www.jianshu.com/p/56ec5c113f1b,如要了解关于Generator,可参看。

Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。

Generator包含next和yield,一旦步骤遇到yield或return,就停止,遇到next就进行下一步,直到结束

Generator函数定义:
// 需要babel-polyfill支持
{// genertaor基本定义let tell=function* (){yield 'a';yield 'b';return 'c'};let k=tell();console.log(k.next());console.log(k.next());console.log(k.next());console.log(k.next());
}

为其他数据结构部署Iterator接口,实现遍历,不光可以按照之前Iterator接口手动实现的写法,还可以使用Generator。

Generator就是一个遍历器生成接口
Generator 应用,实现遍历器接口(一种应用情景)
{let obj={};obj[Symbol.iterator]=function* (){yield 1;yield 2;yield 3;}for(let value of obj){console.log('value',value);}
}
Generator最大的优势 : 状态机

比如一个对象只有三种状态,A,B,C ,他们会在这三种状态中循环出现。

{let state = function* (){// 因为一直都是true,所以会一直循环while(1){yield 'A';yield 'B';yield 'C';}}let status = state();console.log(status.next());// Object {value: 'A',  done: false}console.log(status.next());// Object {value: 'B',  done: false}console.log(status.next());// Object {value: 'C',  done: false}console.log(status.next());// Object {value: 'A',  done: false}console.log(status.next());// Object {value: 'B',  done: false}...
}
async…await 语法是Generator函数的一个语法糖
{let state=async function (){while(1){await 'A';await 'B';await 'C';}}let status=state();console.log(status.next());console.log(status.next());console.log(status.next());console.log(status.next());console.log(status.next());
}
Generator的应用:

1、剩余抽奖次数逻辑

{let draw=function(count){//具体抽奖逻辑console.info(`剩余${count}次`)}let residue=function* (count){while (count>0) {count--;yield draw(count);}}let star=residue(5);let btn=document.createElement('button');btn.id='start';btn.textContent='抽奖';document.body.appendChild(btn);document.getElementById('start').addEventListener('click',function(){star.next();},false)
}

2、长轮巡

{// 长轮询let ajax=function* (){yield new Promise(function(resolve,reject){//模拟每200毫秒请求一次setTimeout(function () {resolve({code:0})}, 200);})}let pull=function(){// generator实例let genertaor=ajax();let step=genertaor.next();// step.value就是Promise实例step.value.then(function(d){if(d.code!=0){setTimeout(function () {console.info('wait');pull()}, 1000);}else{console.info(d);}})}pull();
}

Decorator(修饰器)[针对类]

基本概念 :

修饰器是一个函数,用来修改类的行为(或扩展类的功能)

使用准备:

1、除了babel-polyfill,还需要安装一个插件包:
babel-plugin-transform-decorators-legacy

2、修改.babelrc文件
{ "presets":["es2015"], "plugins":["transform-decorators-legacy"] }
3、再重启服务

基本用法:

声明函数体:

{// 声明一个修饰器let readonly = function(target, name, descriptor){descriptor.writable = false; //描述是否可写return descriptor}
}

使用(在类的里面):

{class Test{@readonlytime(){return '2018-03-09'}}
}let test = new Test();
// 尝试修改类
test.time = function(){console.log('reset time');
}console.log(test.time());//会报错提示无法修改只读属性time
Uncaught TypeError:  Cannot assign to read only property 'time' of object '#<Test>'

在类的外面使用:

{let typename=function(target,name,descriptor){target.myname='hello'; // target指的就是类本身}@typenameclass Test{}console.log('类修饰符',Test.myname);// 第三方库修饰器的js库:core-decorators; // 可以通过npm安装:npm install core-decorators// import 进来以后,直接就可以@使用
}
Decorator的应用:

做埋点,日志统计
把埋点系统抽离出来,成为一个可复用的模块

{let log=(type)=>{return function(target,name,descriptor){let src_method=descriptor.value;descriptor.value=(...arg)=>{src_method.apply(target,arg);console.info(`log ${type}`);}}}class AD{@log('show')show(){console.info('ad is show')}@log('click')click(){console.info('ad is click');}}let ad=new AD();ad.show();ad.click();
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 一款不包含框架(例如:Vue、React、Angular 等)的 Webpack 启动器

    一款不包含框架&#xff08;例如&#xff1a;Vue、React、Angular 等&#xff09;的 Webpack 启动器 地址见&#xff1a;https://github.com/SinanMtl/webpack-simple-starter build/ # Webpack configurations config/ # Dev and prod configurations src/ # …...

    2024/4/28 18:32:25
  2. 西安钻石恒美双眼皮怎么样

    ...

    2024/4/21 6:38:33
  3. 双眼皮切割后遗症

    ...

    2024/4/21 6:38:33
  4. 16岁做埋线双眼皮消肿快吗

    ...

    2024/4/21 6:38:32
  5. 韩式粘连双眼皮三点埋线法

    ...

    2024/4/21 6:38:31
  6. 美式亮瞳韩国双眼皮价格

    ...

    2024/4/21 6:38:29
  7. Angular解决http请求跨域问题

    创建代理配置文件 proxy.conf.json 假设要把所有到 http://localhost:4200/api 的调用都转发给运行在 http://localhost:8888/api 上的服务器&#xff0c;或者把到 http://localhost:4200/appapi 的调用转发给运行在 http://xxx.xxxx.net/ 上的服务器 则在 proxy.conf.json 中…...

    2024/4/21 6:38:30
  8. 天津微创埋线双眼皮大概多少钱

    ...

    2024/5/10 1:22:12
  9. 连续天津埋线双眼皮多少钱

    ...

    2024/4/21 6:38:26
  10. 割完双眼皮一大一小

    ...

    2024/4/21 6:38:26
  11. 双眼皮埋线手术过程

    ...

    2024/4/21 6:38:25
  12. 双眼皮埋线注意事项

    ...

    2024/4/21 6:38:24
  13. java定时任务实现的4种方式

    1. java自带的TimerTimer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("Times up!");}},3*1000,1000);2.ScheduledThreadPool-线程池ScheduledExecutorService scheduledThreadPool = Executors.newSchedu…...

    2024/4/21 6:38:22
  14. 埋线法双眼皮适合什么样的眼皮

    ...

    2024/4/21 6:38:21
  15. 三角埋线法双眼皮保持多久

    ...

    2024/4/21 6:38:21
  16. 北京来美安修复韩式双眼皮手术预约

    ...

    2024/4/21 6:38:20
  17. 双眼皮修复 男

    ...

    2024/4/21 6:38:18
  18. angular.animation的使用

    为什么80%的码农都做不了架构师&#xff1f;>>> overview angular-animate.js插件可以对ng-repeat,ng-view,ui-view,ng-include,ng-switch,ng-if,ng-class,ng-show,ng-hide,form,ng-model等指令提供CSS3或者JS动画效果&#xff0c;这些指令分别两个梯队&#xff1a…...

    2024/4/20 19:03:53
  19. 韩国双眼皮医生曹仁昌

    ...

    2024/4/20 19:03:51
  20. 曹仁昌修复双眼皮价格

    ...

    2024/4/20 8:43:27

最新文章

  1. docker自定义网桥和容器的网络IP段

    生产环境中服务器IP基本都是内网ip&#xff0c;有时会和docker网桥以及容器的ip段产生冲突&#xff0c;导致无法访问应用的情况&#xff0c;要避免这种情况可以自己自定义docker的网桥和容器使用的ip段。 需要在docker配置文件中添加配置&#xff0c;编辑文件&#xff1a;vi /e…...

    2024/5/10 7:20:49
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/9 21:23:04
  3. Python读取文件里内容

    如果要读取一个文件里的内容是 # 文件名&#xff1a;db.txt 1 2 3 4代码如下 import requests f open("db.txt", mode"rb") content f.read() f.close()data content.decode(utf-8)# 存到 list 里 data_list data.split(\r\n) print(data_list)# 结果…...

    2024/5/5 8:37:34
  4. 【python】Flask Web框架

    文章目录 WSGI(Web服务器网关接口)示例Web应用程序Web框架Flask框架创建项目安装Flask创建一个基本的 Flask 应用程序调试模式路由添加变量构造URLHTTP方法静态文件模板—— Jinja2模板文件(Template File)<...

    2024/5/8 1:34:38
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/9 15:10:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/9 17:11:10
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57