Javascript(学中总结)笔记

声明变量

关键字

ES5 var 全局作用域下的 (window) var 声明变量

ES6 let const 块级作用域 只有块级作用域的概念

let 声明的变量只在let命令行内存在的代码块中有效

const 声明一个只读的常量 一旦声明就不能改 而且必须要初始化(赋值)

区别:

1.语法的区别

2.作用域不同

3.const 只读的常量

4.重复声明变量?

5.暂时性死区

6.变量提升是否初始化?

操作符

==(不严格的等于)!=(不严格的不等于) =(严格的等于)!(严格的不等于)

1.=== :称为等同符,先类型是否相等 如果相等 再判断值是否相等

2.==:称为等值符,当等号两边的类型相同时,直接比较值是否相等,若不相等 先转换类型 在比较值

!取非 取反

数据类型

在ES5的时候 ,我们认知的数据类型确实是有 6种:Number String Boolean undefinrd Object Null

ES6中 新增了一种Symbol。永不相等 独一无二。

谷歌6,7版本 中 bigInt (大整数) (个人觉得不是)

js数据类型:js数据类型有几种

7种:Number String Boolean undefinrd Object Null Symbol

image-20201210204616988

typeof 用判断数据类型的 返回值 Number String Boolean undefinrd Object Symbol function

image-20201210205008213

instanceof 用于判断对象是谁的实例

hasOwnProperty() 判断某个属性是否存在于某个对象中 in 运算符配合完成

isPrototypeOf() 检测一个对象是否是另一个对象的原型

循环结构

while 循环

while(条件) 语句;
//举栗子
var i = 0
while(i<10){
    console.log(i);
    i=i+1;
}

do while

先循环 后判断 最少要执行一次循环体

do 语句 while(条件)
    //举栗子
var x = 3;
var i =0
do{
    console.log(i);
    i++;
}while(i<x)

for循环

  for (基数器; 循环条件; 累次循环) {
        循环体
    }

扩充:

js性能优化之for循环

1.最常规的写法

for(var i = 0;i<10;i++){
    //do something 
}

2.循环次数为变量的情况

for(var i = 0;i<arr.length;i++){
    //do something 
}

3.变量情况的优化

for(var i = 0,l = arr.length;i<l;i++){
    //do something 
}

4.也可以这样写

var i = 0;
var l = arr.length;
for(;i<l;i++){
    //do something 
}

5.优化版本的升级版

for(var i = arr.length - 1;i>=0;i--){
    //do something 
}

for…in循环

主要运用于对象

var obj = { a: 1, b: 2, c: 3 }
for (const key in obj) {
    console.log("键名",key);
    console.log("键值",obj[key]);
}
for (const key in object) {
    if (object.hasOwnProperty(key)) {
        const element = object[key];
        
    }
}

for…of

数组

var  arr = [1,2,3,4,5,1]
for (const key of arr) {
    console.log(key);
}

set map

var s = new Set([1,2,3,4,5,6])
for (const key of s) {
    console.log(key);
}
var m = new Map()
m.set('a',1)
m.set("b",2)
for (var [key,value] of m) {
    console.log(key +":"+value);
}

nodeList 字符串 arguments

// 字符串
var str = "hello";

for (let s of str) {
    console.log(s); // h e l l o
}

// DOM NodeList对象
let paras = document.querySelectorAll("p");

for (let p of paras) {
    p.classList.add("test");
}

// arguments对象
function printArgs() {
    for (let x of arguments) {
        console.log(x);
    }
}
printArgs('a', 'b');// 'a' 'b'

[迭代的五种方法][https://www.cnblogs.com/lcspring/p/11167165.html]

数组

[js数组常用方法][https://blog.csdn.net/qq_39132756/article/details/85007082]

函数

普通函数

function fn() {
    console.log(123);
}
fn()//有名函数

//通过自变量创建的函数
var fn =function(){console.log(123);}

//匿名函数
(function(){console.log(123);}())
//通过构造函数
var fn = new Function('console.log(123);')

构造函数

function  Person(name,age,company) {
    this.name = name;
    this.age = age;
    this.company = company;
    this.sayName = function () {
        console.log(this.name);
    }
}

var yunmu =new Person('云牧',18,"潭州教育")
var deft = new Person('deft',18,'潭州教育')
var leap = new Person('leap',18,"潭州教育")
var qinqi = new Person('倾奇',18,'潭州教育')
console.log(yunmu);
console.log(deft);
console.log(leap);
console.log(qinqi);

每次new实例的时候会把构造函数中的方法也实例了 对内存有损耗 节省内存 原型模式

image-20201211202054520

但是如果原型模式中出现参数是引用类型 如果去改变值通过P1 的话 会直接改变原型上的值 导致所拿到是数据不是所想要的 提出了组合模式

image-20201211202427518

寄生构造函数模式 除了用new操作符并把使用的包装函数叫做构造函数之外 几乎和工厂模式一模一样

image-20201211202658802

稳妥模式

image-20201211202902078

引申工厂模式 工厂模式和构造函数模式 区别:

对比工厂模式的不同之处有:

1.没有显式创造对象

2.直接将属性和方法赋给了this

3.没有return语句

构造函数和普通函数的区别:

1.构造函数其实也是一个普通函数 普通函数和构造函数首字母不同 普通函数小写 构造函数大写

2.构造函数用创建了一个新的实例对象

3.调用方式不一样 构造函数new 普通函数之间通过函数名调用

4.构造函数内部是用this来构造方法和属性

5.普通函数返回没有值 所以undefined ;构造函数 会返回一个新的对象

6.instanceof可以检查一个对象是否是一个类的实例

8.构造函数的执行流程
A.立刻在堆内存中创建一个新的对象
B.将新建的对象设置为函数中的this
C. 逐个执行函数中的代码
D.将新建的对象作为返回值

普通函数和箭头函数的区别

1.外形不同

2.箭头函数 匿名函数

3.箭头函数是不可以作为构造函数的

4.箭头函数中this指向不同

5.箭头函数中不具备arguments对象的

6.其他

6.1 箭头函数不能Generator函数 。

6.2 箭头函数不具备prototype原型对象。

6.3 箭头函数是不具备super

6.4 箭头函数不具备new.target(new.target该表达式在函数中使用,返回的是当前的构造函数。若该函数不是通过new调用的,则返回undefined)

对象

创建对象的几种方式

1.调用系统的构造函数创建对象 var obj = new Object();以字面量的方式创建对象。

2.工厂模式(自定义构造函数创建对象)

3.构造函数模式

4.原型模式

5.组合模式

6.动态原型模式

7.寄生构造函数模式和稳妥模式

8.Object.create()

[js中对象常用方法][https://blog.csdn.net/qq_42278182/article/details/93618323]

函数高级

闭包

什么闭包 就是定义一个在函数内部的函数

特性 函数嵌套函数 内部函数可以访问到外部函数的变量 参数和变量不会被回收

闭包中的this

递归

什么是递归 函数自身调用自身

递归 递(递进)归(归来)递归有去有回

function factorial(n) {
    if (n <= 1) {
        return 1;
    } else {
        return factorial = n * factorial(n - 1);
    }
}
console.log(factorial(5));

image-20201211214434698

循环

var chen = 1;
function factorial(n) {
    if (n<=1) {
        return 1;
    }
    while (n) {
        chen *= n;
        n--;
    }
    return chen;
}
console.log(factorial(5));

image-20201211215045089

尾递归优化那么请问优化的是什么 内存

尾调用自称尾递归

function factorial(n,total) {
    if (n <= 1) {
        return total;
    } else {
        return factorial(n-1,n*total);
    }
}
console.log(factorial(5,1));

高阶函数

就是操作该函数的函数,该函数接受一个或多个函数作为参数并且返回一个新的函数

var even = function (x) {
    return x % 2 === 0;
}
var odd = not(even)
function not(fn) {
    return function () {
        var result = fn.apply(this, arguments)
        return !result;
    }
}
//every()
console.log([1,1,3,5,5].every(odd));

函数柯里化 分步(分部)

function createCurry(func, args) {
    var arity = func.length;
    console.log("arity",arity);
    var args = args || []
    console.log("args",args);
    return function () {
        console.log("arguments",arguments);
        var _args = [].slice.call(arguments);
        console.log("_args",_args);
        var a = [].push.apply(_args, args);
        console.log("push",a);
        console.log("_args.length",_args.length);
        if (_args.length < arity) {
            return createCurry.call(this, func, _args)
        }
        return func.apply(this, _args)
    }
}
function check(str, reg) {
    console.log("check",str, reg);
    //str 是否符合reg验证
    //test() 方法  用于检测一个字符串是否匹配某个模式
    return reg.test(str);
}
var _check = createCurry(check)
var checkPhone = _check(/^1[34578]\d{9}$/);
// var checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
checkPhone('123596');
// checkEmail('xxxxx@test.com');

箭头函数

箭头函数this 为父作用域的this 而不是调用时的this (函数体内的this对象 就是定义是所在的对象 而不是使用是所在的对象)

普通函数中的this指向的是调用它的 对象,如果说没有直接调用对象,会指向undefined 或window 一般指向widow 在严格模式下会只指向undefined

继承

1.原型链继承

2.借用构造函数(经典继承)

3.组合继承

4.原型式继承

5.寄生式继承

6.寄生组合式继承

ES6继承

class People{
    constructor(name = "我是你爸",age = 100){
        this.name = name;
        this.age = age;
    }
    eat(){
        console.log(`${this.name}今年${this.age}`);
    }
}
class Son extends People{
    constructor(name="生来就是儿子",age=18){
        super(name,age)
    }
    eat(){
        super.eat()
    }
}
let s = new Son('儿子')
s.eat()

DOM操作事件

BOM操作事件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-897ex5Be-1620116170926)(D:\HUAWEI\Typora作业笔记\1945949-20200518213413606-1761707733.png)]

js浅拷贝与深拷贝的区别和实现方式

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力
<script>
    var a 1;
    b = a; //浅内会开辟一个新的内存空间, 此时b和a都是相互独立的
    b = 2;
    console.log(a);//1
</script>

2.如果是引用数据类型, 名字存在栈内中, 值存在内存在中,但是栈内会提供一个引用的地址指向堆内存中的值

比如栈拷贝:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFSdDVVX-1620116170926)(D:\HUAWEI\Typora作业笔记\1.webp)]

当b = a进行拷贝时, 其实复制的是a的引用地址, 而并非堆里面的值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dcfWRf0R-1620116170927)(D:\HUAWEI\Typora作业笔记\15037426-7bf9efc3a6e90bea.webp)]

哪, 要是在内堆存中也开辟一个新的内存专门为b存放值,就像基本类型那样,岂不是就达到深拷

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2Al6OF9-1620116170927)(D:\HUAWEI\Typora作业笔记\2.webp)]

3.实现浅拷贝的方法

(1) for…in只循环第一层

<script>
    function simpleCopy(obj1){
    var obj2 = Array.isArray(obj1) ? [] : {};
    for(let i in obj1){
        obj2(i) = obj1(i);
    }
    return obj2;
}
var obj1 = {
    a: 1,
    b: 2,
    c: {
         d: 3
    }
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a);//1
alert(obj2.a);//3
alert(obj1.c.d);//4
alert(obj2.c.d);//4
 </script>

Object.assign方法

<script>
    var obj = {
        a: 1,
        b: 2
    }
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a);//3
</script>

直接用=赋值

<script>
    let a[0,1,2,3,4],
        b = a;
console.log(a===b);
a[0]=1;
console.log(a,b);
</script>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICprpr9z-1620116170928)(D:\HUAWEI\Typora作业笔记\15037426-1c7b29547b2a8794.webp)]

用slice实现对数组的深拷贝

<script>
    //当数组里面的值是基本数据类型, 比如String, Number, Boolean时,属于深拷贝
    //当数组里面的值是引用数据类型, 比如Object, Array时,属于栈拷贝
   var arr1 = ["1","2"."3"];
   arr2[1] = arr.slice(0);
   arr[1] = "9";
   console.log("数组的原始值 :" + arr1);
   console.log("数组的新值: " + arr2);
 </script>

用concat实现对数组的深拷贝

<script>
 //当数组里面的值是基本数据类型,比如String, Number, Boolean时,属于深拷贝
    var arr1 = ["1","2","3"];
    var arr2 = arr1.concat();
    arr2[1] = "9";
    console.log("数组的原始值: " + arr1);
    console.log("数组的新值: " + arr2);
    //当数组里面的值是引用数据类型,比如Object, Array时,属于栈拷贝
    var arr1 = [(a:1),{b:2},{c:3}];
    var arr2 = arr1.concat();
    arr2[0].a = "9";
    console.log("数组的原始值: " + arr1[0].a);//数组的原始值 : 9
    console.log("数组的新值: " + arr2[0].a);//数组的新值 : 9
 </script>

直接使用var newObj = .create(oldObj), 可以达到深拷贝的效果

<script>
    function deepClone(initalObj,function) {
    var obj = finaObj || {};
    for(var i in initalObj) {
        var prop = initalObj[i];
        if(prop === obj) {
            continue;
        }
        if(typeof prop === 'object'){
            obj[i] = (prop.constructor === Array ? [] : Object.create(prop);
        }else{
                obj[i] = prop;
            }
    }
    return obj;
}
</script>

使用扩展运算符实现深拷贝

<script>
    //当value是基本数据类型,比如String, Number,Boolean时,是可以使用扩展运算符进行深拷贝的
    //当value是引用类型的值,比如Object,Array, 引用类型进行深拷贝也只是拷贝了引用地址,所以属于栈拷贝
    var car = {brand: "BMW",price: "380000",length: "5米"}
    var car1 = {...car, price: "500000"}
    console.log(car1);
    console.log(car);
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客云曦

你的鼓励就是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值