js基础知识复习2

第一章 走进 JAVASCRIPT 黑洞

1.传值和传址

基本数据类型复制的是值,

引用数据类型复制的是地址,

/*
let a = 1;
let b = a;
console.log(a,b) //1,1
b = 2;
console.log(a,b) //1,2
*/
let a = {name:"kangxinzhi"};
let b = a;
console.log(a,b) //{name:"kangxinzhi"},{name:"kangxinzhi"}
b.name = "kxz"
console.log(a,b)  //{name:"kxz"},{name:"kxz"}

2.null和undifined详解

基本数据类型空为undifined

引用数据类型空为null

null是个对象

3.环境污染(局部污染外部)

/*
name="kxz"
function change(){
   name="kang"   
}
change();
console.log(name) //"kang"
*/
//原因:变量未声明,成为全局变量,造成全局污染。解决方案:使用严格模式提示

"use strict"
name="kxz"
function change(){
   name="kang"   
}
change();
console.log(name) //"kxz"

第二章 JavaScript 运算符与流程控制

1.比较运算符注意事项

let a=1;
let b="1";
a==b    //true存在隐式转换,这里的b转化为数字类型 数字和数字的比较
a===b  //false   字符串和数字的比较

2.break,continue和label标签的使用

break停止整个循环

continue停止当前循环走下个循环

testlabel:for(let i=0;i<10;i++){
  for(let j=0;j<10;j++){       
        if(i+j>10){
           break testlabel; //跳到最外层testlabel循环       
        }
    }
}

3.for-in;for-of的使用

for-in用来遍历数组时返回的下标;遍历对象时返回的是对象的key

for-of用来遍历数组时返回的是值;遍历对象时返回的是对象的value(用来处理迭代对象)

let arr = ["apple","banana","orange","melon"];
let msg = {name:"kang",age:"18",sex:"man"};

for(let index in arr){
   console.log(i); //0,1,2,3
   console.log(arr[i]); //"apple","banana","orange","melon"               
}
for(let value of arr){
   console.log(value); //"apple","banana","orange","melon"       数组时迭代对象       
}
for(let key in msg){
   console.log(key); //name,age,sex
   console.log(msg[key]); //"kang","18","man"               
}
for(let value of msg){
   console.log(value); //报错msg不是迭代对象
}
for(let value of "kang"){
  console.log(value) //k a n g 字符串也是可迭代对象
}

第三章 JavaScript 值类型使用

1.typeof 能判断基本类型和function

A instanceof Array 判断复杂数据类型,它的原理是判断A的protote是否在Array原型链上

2.模板字面量的使用和字符串转义( /t 制表符  /n换行符) 

let year="1998年";
let name="康心志";
console.log(name+"出生于"+year);//康心志出生于1998年
console.log(`${name}出生于${year}`)//康心志出生于1998年
let lessons=[{title:"vue"},{title:"react"},{title:"angular"}];
console.log(`${lessons.map(e=>{e.title})})  // , ,
console.log(`${lessons.map(e=>{return e.title})})//vue react angular
console.log(`${lessons.map(e=>e.title)}`) //vue react angular

3.标签模板实例操作

在模板字面量``前加一个函数,函数的第一个参数是模板中的string,第二个可用扩展元素表示剩余的所有参数它表示的是每个${}的内容

let year="1998年";
let name="康心志";
function tag(strings,...vars){
   console.log(strings);
   console.log(vars)      
}
console.log(tag`${name}出生于${year}`)
//["", "出生于", "", raw: Array(3)]
//["康心志", "1998年"]

4.字符串的常用方法

toUpperCase()大写  toLowerCase()小写  trim()去除字符串两端空格  charAt()获取某个下标的字符  

slice()截取字符串  substring()截取字符串  substr()截取字符串

indexOf()查找某个字符串的坐标,没有就返回-1,第二个参数表示从第几个字符串开始查找  includes()是否存在某个字符返回布尔值,第二个参数表示从第几个字符开始查找  lastIndexOf()从末尾开始查找

startsWidth()字符串是否以某个字符开头  endsWidth()字符串是否以某个字符结尾

replace()字符串替换  repeat()重复输出某个字符串

split()字符串转为数组  数组.join(,)数组转为字符串

let a="KangXinZhi";
a.toUpperCase()//"KANGXINZHI" 
a.toLowerCase();//"kangxinzhi"
"    xxx  ".trim()//"xxx"
a.charAt(5)//i
a.slice(1);//angXinZhi
a.substring(1);//angXinZhi
a.substr(1);//angXinZhi
a.slice(1,3);//an
a.substring(1,3);//an
a.substr(1,3);//ang
a.slice(-3,-1);//Zh
a.substring(-3,-1);//KangXinZhi
a.substr(-3,2);//Zh
a.replace("Kang","k")//kXinZhi
"*".repeat(3);//"***"
a.split("");//["K", "a", "n", "g", "X", "i", "n", "Z", "h", "i"]
["k","x","z"].join(,);//"kxz"

 5.类型转换和隐式转换

字符串,对象的toString()方法,转为字符串

字符串  使用运算符+-*/转为数字

字符串或数字 前使用!!转为布尔值

String()转字符串,Boolean()转布尔值,Number()转数字,Object()转对象

boolean只有6种情况为false 其他为true

1、undefined(未定义,找不到值时出现)

2、null(代表空值)

3、false(布尔值的false,字符串"false"布尔值为true)

4、0(数字0,字符串"0"布尔值为true)

5、NaN(无法计算结果时出现,表示"非数值";但是typeof NaN==="number")注意NaN===NaN为false 它是唯一一个不等于自身的

6、""(双引号)或''(单引号) (空字符串,中间有空格时也是true

注意空数组空对象,负值转的布尔值时都为true

6.Number的一些常用函数

number.toString()数字转为字符串  Number.isInteger(number)判断数字是否是整数  Number.isNaN(number)判断是否是NaN  Object.is(number,NaN)判断是否是NaN

parseInt()转为整形  parseFloat()转为浮点数  Number.toFixed(1)保留一位小数

Math.max()  Math.min()  Math.ceil()取最接近的最大整数  Math.floor()取最接近的最小整数  Math.round()四舍五入  Math.random()随机数

7.Data的一些常用函数

时间戳(TIMESTAMP)指从1970-01-01 00:00:00到现在的毫秒数

new Date() //获取当前时间ISO
Date.now()  //当前时间戳TIMESTAMP
const start=Date.now();
for(let i=0;i<20000000;i++)
const end =Date.now();
console.log(end-start) //计算脚本执行时间
console.time("for")
for(let i=0;i<20000000;i++)
console.timeEnd("for") //计算脚本执行时间

ISO和TIMESTAMP的转换

ISO转TIMESTAMP
const date=new Date();
console.log(date*1);
console.log(Number(date));
console.log(date.valueOf());
console.log(date.getTime());
TIMESTAMP转ISO
const TIMESTAMP=date.valueOf();
console.log(new Date(TIMESTAMP));

日期格式格式化

function dateFormat(date,format="YYYY-MM-DD hh:mm:ss"){
    const config = {
        YYYY : date.getFullYear(),
        MM : date.getMonth(),
        DD : date.getDate(),
        hh : date.getHours(),
        mm : date.getMinutes(),
        ss : date.getSeconds()
    }
     for(const key in config){
         format=format.replace(key,config[key]);
    }
     return format;
}
console.log(dateFormat(date)) //2020-9-21 10:29:14
console.log(dateFormat(date,"YYYY年MM月"))//2020年9月

优秀的日期处理库moment.js

http://momentjs.cn/

//npm install moment --save  
moment().format('MMMM Do YYYY, h:mm:ss a'); // 十月 21日 2020, 10:31:44 上午
moment().format('dddd');                    // 星期三
moment().format("MMM Do YY");               // 10月 21日 20
moment().format('YYYY [escaped] YYYY');     // 2020 escaped 2020
moment().format();                          // 2020-10-21T10:31:44+08:00

第四章 JavaScript 数组挖掘

1.数组创建的小细节

用new Array()创建数组时,当只填入一个数字,它表示创建的长度是该数字,其每一项的值是undifined

为了解决这一问题,新版可以用Array.of()来创建,

let arr=new Array(6);
arr.length //6
arr[0]      //undifined
let arr2=Array.of(6);
arr2.length  //1
arr2[0]     //undifined

 2.数组的常用方法

push()  pop()  unshift()  shift()  fill()填充  copywithin(i,j,k)用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。

slice(i,j)截取数组从第i截取到第j项,不改变原数组  splice(i,j,k)截取数组从第i截取j个元素,用k替换掉其内容,改变原数组

indexOf()查找某项的下标,没有就返回-1,第二个参数表示从第几项开始查找  includes()是否存在某个项返回布尔值,第二个参数表示从第几项开始查找  lastIndexOf()从末尾开始查找

find(callback)查找数组中第一个符合条件的值  findIndex(callback)查找数组中第一个符合条件的值的索引

sort((a,b)=>{return a-b})数组排序

清空数组的几种方式:

let arr=[1,2,3,4];
arr=[];
arr.length=0;
arr.splice(0,arr.length);
while(arr.pop()){};
while(arr.shift()){};
//手写find
function myfind(arr,callback){
   for(let value of arr){
       if(callback(value)){return value}
   }   
    return undefined;
}
myfind([1,2,3,4,5],e=>{return e==3}) //3
//手写sort
function mysort(arr,callback){
   for(let m in arr){
       for(let n in arr){
           if(callback(arr[m],arr[n])<0) {
               let t=arr[n];
               arr[n]=arr[m];
               arr[m]=t;
            }  
        }   
   }  
    return arr;       
}    

  2.数组的遍历

1.forEach((item,index,arr)=>{},{}) 遍历数组,第一参数回调函数(每一项,索引值,原数组),第二个参数this指向的对象,不填的话this指向windows

2.使用迭代器iterator

let arr=["kang","xin","zhi"];
let arrkeys=arr.keys();
arrkeys.next();//{value: 0, done: false}
arrkeys.next();//{value: 1, done: false}
arrkeys.next();//{value: 2, done: false}
arrkeys.next();//{value: undefinew, done: true}

let arrvalues=arr.values();
arrvalues.next();//{value: "kang", done: false}
arrvalues.next();//{value: "xin", done: false}
arrvalues.next();//{value: "zhi", done: false}
arrvalues.next();//{value: undefined, done: true}
for(let values of arr.values()){
    console.log(values)//kang xin zhi
}
for(let keys of arr.keys()){
    console.log(keys )//0 1 2
}
for(let [keys,values] of arr.entries()){
    console.log(values)//kang xin zhi
    console.log(keys )//0 1 2
}

3.every()和some()

every()是对数组中每一项运行给定函数,如果该函数所有一项返回true,则返回true。一旦有一项不满足则返回flase

some()是对数组中每一项运行给定函数,如果该函数满足任一返回true,则返回true

var arr = [ 1, 2, 3, 4, 5, 6 ]; 
 
console.log( arr.every( function( item, index, array ){ 
    console.log( 'item=' + item + ',index='+index+',array='+array ); 
    return item > 3; 
}));
//item=1,index=0,array=1,2,3,4,5,6
//false


console.log( arr.some( function( item, index, array ){ 
    console.log( 'item=' + item + ',index='+index+',array='+array ); 
    return item > 3; 
})); 
//item=1,index=0,array=1,2,3,4,5,6
//item=2,index=1,array=1,2,3,4,5,6
//item=3,index=2,array=1,2,3,4,5,6
//item=4,index=3,array=1,2,3,4,5,6
//true 

4.filter过滤器

let arr=[100,55,32,65,84]
arr.filter((item,index,value)=>{return item>60})//[100,65,84]
//手写 filter
function myfilter(arr,callback){
   let newarr=[];
   for(let value of arr){
       if(callback(value)==true){
            newarr.push(value)  
       }
   }  
    return newarr;    
}
myfilter([100,55,32,65,84],(item,index,value)=>{return item>60})
//[100, 65, 84]

 5.map映射数组

对于值类型来说返回一个新的数组

对于引用类型来说会改变原数组的内容(可以不改变)

let arr=[1,2,3,4,5]
let arr2=arr.map((value,index,array)=>{return value+1})
console.log(arr)//[1,2,3,4,5]
console.log(arr2)//[2,3,4,5,6]

let arr3=[{name:"kang",age:18},{name:"xin",age:19},{name:"zhi",age:20}]
arr3.map((value)=>{value.sex="man"})
console.log(arr3)
//[{name:"kang",age:18,sex:"man"},{name:"xin",age:19,sex:"man"},{name:"zhi",age:20,sex:"man"}]

//若想不改变引用类型原数据,可以使用以下方法
let arr4=[{name:"kang",age:18},{name:"xin",age:19},{name:"zhi",age:20}]
let arr5=arr4.map((value)=>{return Object.assign({sex:"man"},value) })
let arr6=arr4.map((value)=>{return {name:value.name,age:value.age,sex:"man"}})
//arr4  [{name:"kang",age:18},{name:"xin",age:19},{name:"zhi",age:20}]
//arr5  [{name:"kang",age:18,sex:"man"},{name:"xin",age:19,sex:"man"},{name:"zhi",age:20,sex:"man"}] 
//arr6  [{name:"kang",age:18,sex:"man"},{name:"xin",age:19,sex:"man"},{name:"zhi",age:20,sex:"man"}]

6.reduce

/*
reduce比之前见到的遍历函数的回调函数中多了一个pre参数,它表示函数每次遍历的返回值,若不给定其初始值,它第一次就表示数组中第一项,接下来表示每一项遍历的返回值。
若给reduce(callback,n)第二个参数n,则表示pre的初始值是n,接下来表示每一项遍历的返回值。
*/

let arr=[1,2,3,4,5];
arr.reduce(function(pre,value,index,array){
    console.log(pre,value)
})
//1             2
//undefined  3
//undefined  4
//undefined  5

arr.reduce(function(pre,value,index,array){
    console.log(pre,value)
    return "kxz"
},0)
//0              1
//kxz           2
//kxz           3
//kxz           4
//kxz           5

//判断数组中的最大值
function maxnum(array){
   return array.reduce((pre,value)=>{
        return pre>value?pre:value;
  })
}
maxnum([99,56,43,41,255]); //255

第五章 好用的 JavaScript Symbol 类型

1.symbol的定义

Symbol用于防止属性名冲突而产生的,比如向第三方对象中添加属性时。

symbol定义的值永远是唯一的

let kxz= Symbol();
let kang = Symbol();
console.log(kxz); //symbol
console.log(kxz== kang ); //false

//symbol不可以添加属性
kxz.name = "康心志";
console.log(hd.name); //报错

2.symbol描述参数

//可传入字符串用于描述Symbol,方便在控制台分辨Symbol
let kxz= Symbol("is name");
let kang = Symbol("这是一个姓");
console.log(kxz); //Symbol(is name)
console.log(kang.toString()); //Symbol(这是一个姓)

//传入相同参数Symbol也是独立唯一的,因为参数只是描述而已,但使用 Symbol.for则不会
let kxz2= Symbol("kang");
let kxz3 = Symbol("kang");
console.log(kxz2== kxz3); //false

//使用description可以获取传入的描述参数
let kxz4= Symbol("kang");
console.log(hd.description); //kang

3.Symbol.for和Symbol.keyFor 

//Symbol.for根据描述获取Symbol,如果不存在则新建一个Symbol
//使用Symbol.for会在系统中将Symbol登记
//使用Symbol则不会登记
let hd = Symbol.for("后盾人");
let edu = Symbol.for("后盾人");
console.log(hd == edu); //true


//Symbol.keyFor 根据使用Symbol.for登记的Symbol返回描述,如果找不到返回undefined 。
let hd = Symbol.for("后盾人");
console.log(Symbol.keyFor(hd)); //后盾人

let edu = Symbol("houdunren");
console.log(Symbol.keyFor(edu)); //undefined

4.对象属性

Symbol 是独一无二的所以可以保证对象属性的唯一。

  • Symbol 声明和访问使用 [](变量)形式操作

  • 也不能使用 . 语法因为 .语法是操作字符串属性的。

//下面写法是错误的,会将symbol 当成字符串symbol处理
let symbol = Symbol("后盾人");
let obj = {
  symbol: "hdcms.com"
};
console.log(obj);

//正确写法是以[] 变量形式声明和访问
let symbol = Symbol("后盾人");
let obj = {
  [symbol]: "houdunren.com"
};
console.log(obj[symbol]); //houdunren.com

5.遍历属性

//Symbol 不能使用 for/in、for/of 遍历操作
let symbol = Symbol("后盾人");
let obj = {
  name: "hdcms.com",
  [symbol]: "houdunren.com"
};

for (const key in obj) {
  console.log(key); //name
}

for (const key of Object.keys(obj)) {
  console.log(key); //name
}


//可以使用 Object.getOwnPropertySymbols 获取所有Symbol属性
for (const key of Object.getOwnPropertySymbols(obj)) {
  console.log(key);
}

//也可以使用 Reflect.ownKeys(obj) 获取所有属性包括
Symbolfor (const key of Reflect.ownKeys(obj)) {
  console.log(key);
}

//如果对象属性不想被遍历,可以使用Symbol保护
const site = Symbol("网站名称");
class User {
  constructor(name) {
    this[site] = "后盾人";
    this.name = name;
  }
  getName() {
    return `${this[site]}-${this.name}`;
  }
}
const hd = new User("向军大叔");
console.log(hd.getName());
for (const key in hd) {
  console.log(key);
}

 6.对象

1.查看对象的属性

对象自己的属性:obj.hasOwnProperty(属性)

对象自己和原型上的属性:属性  in   obj

设置自己的属性:Object.setPrototypeOf(属性)

 对象的合并:Object.assgin({a:1},{b:2}) //{a:1,b:2}

2.浅拷贝,深拷贝

浅拷贝:使用for/in  Object.assgin  展开语法

深拷贝:

        let kxz = { name: "kxz", user: { age: 18 } }
        function deepcopy(obj) {
            let newobj = obj instanceof Array ? [] : {};
            for(let [k,v] of Object.entries(obj)){
                newobj[k]=v instanceof Object ? deepcopy(v):v;
            }
            return newobj;
        }
        let kxz2=deepcopy(kxz);
        kxz2.user.age=19;
        console.log(kxz);
        console.log(kxz2);

 3.构造函数

定义:通过  new 函数名    来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。

对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。

4.面向对象抽象设置

Object.getOwnPropertyDescriptors(对象名); //显示对象的所有权限(value值,writeable是否可写,enumerable是否可遍历,configurable是否可删除)

Object.defineProperty(对象名,属性名,{value:'新值',writeable:false,enumerable:false,configurable:false}) //修改或添加属性及其权限

Object.isExtensible(对象名)// 判断是否能向对象中添加属性

Object.preventExtensions(对象名)//禁止向对象添加属性

Object.seal()//方法封闭一个对象,阻止添加新属性并将所有现有属性标记为 configurable: false

Object.isSealed 如果对象是密封的则返回 true,属性都具有 configurable: false

Object.freeze () //冻结对象后不允许添加、删除、修改属性,writable、configurable都标记为false

Object.isFrozen()方法判断一个对象是否被冻结

 5.属性访问器

getter方法用于获得属性值,setter方法用于设置属性,这是JS提供的存取器特性即使用函数来管理属性。

  • 用于避免错误的赋值
  • 需要动态监测值的改变
  • 属性只能在访问器和普通属性任选其一,不能共同存在

getter/setter

向对是地用户的年龄数据使用访问器监控控制

"use strict";
const user = {
  data: { name: '后盾人', age: null },
  set age(value) {
    if (typeof value != "number" || value > 100 || value < 10) {
      throw new Error("年龄格式错误");
    }
    this.data.age = value;
  },
  get age() {
    return `年龄是: ${this.data.age}`;
  }
};
user.age = 99;
console.log(user.age);

代理拦截proxy 

代理(拦截器)是对象的访问控制,setter/getter 是对单个对象属性的控制,而代理是对整个对象的控制

  • 读写属性时代码更简洁
  • 对象的多个属性控制统一交给代理完成
  • 严格模式下 set 必须返回布尔值

使用方法:

"use strict";
const hd = { name: "后盾人" };
const proxy = new Proxy(hd, {
  get(obj, property) {
    return obj[property];
  },
  set(obj, property, value) {
    obj[property] = value;
    return true;
  }
});
proxy.age = 10;
console.log(hd);

通过proxy实现双向数据绑定:

<body>
<input type="text" v-model="title" />
<input type="text" v-model="title" />
<div v-bind="title"></div>
</body>
<script>
function View() {
    //设置代理拦截
  let proxy = new Proxy(
    {},
    {
      get(obj, property) {},
      set(obj, property, value) {
        obj[property] = value;
        document
          .querySelectorAll(
            `[v-model="${property}"],[v-bind="${property}"]`
          )
          .forEach(el => {
            el.innerHTML = value;
            el.value = value;
          });
      }
    }
  );
  //初始化绑定元素事件
  this.run = function() {
    const els = document.querySelectorAll("[v-model]");
    els.forEach(item => {
      item.addEventListener("keyup", function() {
        proxy[this.getAttribute("v-model")] = this.value;
      });
    });
  };
}
let view = new View().run();
原文地址:https://www.cnblogs.com/kangxinzhi/p/13842397.html