前端基础 -- JavaScript入门

一、JavaScript基础

1、五种基本数据类型

  • 字符类型‘11’被引号引起来的数据 ---- string
  • 数值型 123 正数、负数、小数、NaN ---- number
  • 布尔型 只有true和false ---- boolean
  • 空值型 只有null ---- object
  • 未定义型 只有undefined ---- undefined
    typeof 检测基本数据类型 console.log(typeof data1);

2、数据类型的转换

  • 强制转换:string(XXX); XXX.to string();
  • 隐式转换:+string 可以转成数字, a+""可以转成字符串,!var 可以转成布尔值

转换成为false的6种情况:null underfined false 0 NaN ‘’

3、自调用函数

var result = (function (age = 18) {
            alert('这个人的年龄是' + age);
            return age;
        })(20);
        console.log(result);

4、Math对象(不需要new关键词创建)

Math.round()    四舍五入
Math.ceil()        向上取整
Math.floor()      向下取整
Math.random()   获取随机数
Math.floor(Math.random()*(5+1))

function randomint(num = 5) {
    return Math.floor(Math.random() * (num + 1)); //返回随机数           
}

5、几种遍历方法

  • for…in
for (const key in obj){
     console.log('属性名',key,'值',obk[key]);
}
  • Object.keys(obj) Object.values(obj)
const obj = {
                id:1,
                name:'小明',
                age:18
        }
        console.log(Object.keys(obj))
        console.log(Object.values(obj))
  • forEach()遍历普通数组
 const arr = [
            { id: 1, name: '小明' },
            { id: 2, name: '小红' },
            { id: 3, name: '小吕' }
        ]
        // 写法1
        arr.forEach(function (item) {
            console.log(item.id + '---' + item.name)
        })
        // 写法2
        arr.forEach( (v)=> {
            console.log(v.id + '---' + v.name)
        })
  • map()映射数组
const arr = [
            { id: 1, name: '小明' },
            { id: 2, name: '小红' },
            { id: 3, name: '小吕' }
        ]
        // 写法1
        arr.map(function (item) {
            console.log(item.id + '---' + item.name)
        })
        // 写法2
        arr.map( (v)=> {
            console.log(v.id + '---' + v.name)
        })
  • forEach:用来遍历数组中的每一项,没有返回值,不影响原数组
  • map:相当与原数组克隆了一份,支持return,可以改变克隆的每项,也不影响原数组

6、数组对象的方法

push   向数组的末尾添加一个或更多元素,并返回新的长度 
                   用法:arrs.push('d', 'e', 'f')
unshift 向数组的开头添加一个或更多元素,并返回新的长度
                  用法: arrs.unshift(44, 55, 66);
pop     删除并返回数组的最后一个元素
                   用法:arrs.pop();
shift    删除并返回数组的第一个元素
                   用法:arrs.shift();
reverse   颠倒数组中元素的顺序
                    用法:.reverse();
sort       对数组的元素进行排序
从小到大 用法:arrs.sort(function (a, b) {
                   return a - b;
                        });
splice   删除元素,并向数组添加新元素
用法:
        // 参数1:要删除元素的索引值   可以用-1代表最后一位
        // 参数2:删除的个数
        // 参数3往后:添加的元素
arrs.splice(0, 1); //删除第一个
arrs.splice(arrs.length, 0, 55, 66, 77);   // 在最后追加数据

slice    从某个已有的数组返回选定的元素
用法:
        // 参数1:选取的开始索引值
        // 参数2:选取的结束索引值(不包括该元素)
arrs.slice(1, 3); //抽取第2第3个数

join    把数组用分隔符号连接成新的字符串
用法:   
arrs.join(',')//用逗号分隔

.concat()  连接两个或更多的数组,并返回结果。
用法:
 // 把 boys 和 girls 合并成一个新的数组all
   写法1const all = [].concat(boys, grils);
   写法2const all = boys.concat(grils);

indexOf  返回当前查找数据的索引值
       //  参数1: 要查找的位置的数据
        //  参数2: 查找起始索引值
用法:arrs.indexOf(33, 3);  //从第4位开始查找33

includes()  判断一个数组是否包含一个指定的值
 用法:  array1.includes(3);  //查看是否包含3

.forEach()   遍历数组
用法:
写法1:arrs.forEach(function (item, index) {
            console.log(item, index);
        });
写法2:arrs.forEach((item, index) => console.log(index, item));

.map() 创建一个新数组,给元素加标签
用法:
写法1const newArrs = arrs.map(function (item) {
            return '<a>' + item + '</a>';
        });
写法2const newArrs = arrs.map(item => '<a>' + item + '</a>');

.filter() 过滤原数组返回一个新数组
用法: const result = arrs.filter(function (item) {
            // return 返回满足过滤规则的数据
            return item > 30;
        });

7、string 对象方法

.split()  把字符串分割为字符串数组
用法:
   const strObj = 'apple-banner-cat';
   const arrs = strObj.split('-');//根据-来分隔

.substring()  提取字符串中两个指定的索引号之间的字符
用法:  var str = "Hello world!";
        console.log(str.substring(3, 7));//提取4~6的字符

.replace() 替换字符
用法:const strObj = new String('吃饭了吗?');
        const newStr = strObj.replace('吗?', '。');

.toLowerCase() 把字符串转换为小写
.toUpperCase()`把字符串转换为大写
用法: const lowStr = str.toLowerCase();
        const lowStr = str.toUpperCase();

.trim() 消除字符串空格
用法:
       const str = '     你 好 吗?      ';
        const newStr = str.trim();

.charAt() 返回在指定位置的字符
用法:
var str="你好呀,在吃饭了吗"
        console.log(str.charAt(5))

8、事件冒泡和事件委托

  • 事件冒泡:当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发.这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到 DOM 树的最上层。
  • 事件委托:让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行。
  • 阻止默认事件:为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止 return false; e.preventDefault();
div.onclick = function (e) {
            // 标签名判断的时候注意大小写
            if (e.target.nodeName === 'LI') {
                alert('实现方式2:你点击了li');
            }
        }
 father.onclick = function (e) {
            console.log('是否包含 on 类名', e.target.classList.contains('on'));
            if (e.target.classList.contains('on')) {
                alert('你点击带 on 类名的 元素');
            }
        }

事件委派添加li 的 父级只需要给父级绑定一次即可只需要确保 li 的父级在页面中即可。事件委派在 列表数据量大的时候,更有优势,如 微博首页数据都是数百上千条,微博列表内容都是后添加的内容。

二、JavaScript高级

1、call , apply , bind 三个方法

  • call , apply , bind 三个方法 可以改变函数内部 this 指向
  • call, apply 和 bind 区别:call ,apply 会直接调用函数,而 bind 返回一个新的函数
  • apply 和 call 的区别:apply 只能传两个实参,第二个实参是数组格式,call 每个实参单独书写
  • bind 和 call 区别:bind 只是把第一个实参传递过去,并在堆空间复制一份新的函数,以返回值形式接受
hhh.apply([11, 22], ['你好', '你不好']);
hhh.call([11, 22], '你好', '你不好');
hhh.bind([11, 22], '你好', '你不好')

2、构造函数

  // 构造函数 ------  标准写法首字母需要大写
        const Person = function () {
        }
        // 原型 -------   函数对象自带原型,在原型上添加的方法会表现在<实例>的 __proto__ 上
        Person.prototype.sayHi = function () {
            console.log('新的对象能说话', this);    // 原型上添加的方法,谁调用了方法,this 就指向谁。
        }

        // 实例 ------- 把实例对象的内存地址赋值给 p1
        const p1 = new Person();
        p1.sayHi();

封装一个jquery库(完整版可以看我的上传资源)

/*!
 * my jQuery JavaScript Library v0.0.1
 *
 * Date: 2019-11-07
 */
(function () {

    // 创建 $ jQuery 函数
    const $ = function (selector) {
        // 内部封装变得复杂了,但是对于用户使用来说变得简单了,通过 $() 就可以创建实例
        return new Init(selector);
    }

    // 通过给 window 对象添加 $ 属性,让内部的 $ 地址添加到 window 对象上
    window.$ = window.jQuery = $;

    // 构造函数
    const Init = function (selector) {
        // 先给实例对象添加 selector 选择器属性,记录起来而已
        this.selector = selector;

        // 通过选择器查找到所有 dom 元素
        const doms = document.querySelectorAll(selector);

        // 先给实例对象添加 length 长度属性
        this.length = doms.length;

        // 先把外面的 this 的内存地址先存起来
        const that = this;

        // 遍历所有的 dom
        doms.forEach(function (item, index) {
            that[index] = item;
        });

    }

    // 原型上添加方法
    // addClass 添加类
    Init.prototype.addClass = function (className) {
        // 传递数据:
        // 形参:className 接收传递的实参
        // this:调用的对象会自动传过来,把内存地址给 this
        // 遍历过程 - 隐式迭代核心
        Array.from(this).forEach(function (item) {
            item.classList.add(className);
        });
        // return this  - 链式编程核心
        return this;
    }

    // removeClass 删除类
    Init.prototype.removeClass = function (className) {
        // 遍历过程 - 隐式迭代核心
        Array.from(this).forEach(function (item) {
            item.classList.remove(className);
        });
        // return this  - 链式编程核心
        return this;
    }

    // toggleClass 切换类
    Init.prototype.toggleClass = function (className) {
        // 遍历过程 - 隐式迭代核心
        Array.from(this).forEach(function (item) {
            item.classList.toggle(className);
        })
        // return this  - 链式编程核心
        return this;
    }


    // 高阶函数 - 1. 把函数作为参数进行传递
    // each 遍历函数
    Init.prototype.each = function (fn) {
        // console.log(fn);     // 接收到传递过来的函数地址,保存到 fn 形参中
        // fn();                // 直接调用 fn(),地址上的 index 和 item 就没有值,所以调用的时候要传参
        for (let i = 0; i < this.length; i++) {
            // fn 函数是传过来的,在 each 内部调用,传递参数 i 作为 index,传递 this[i] 作为 item
            // 通过 call 或 apply ,可以在调用函数的时候,把第一个实参传递过去给内部this
            // 预期希望,调用的时候  item === this
            fn.call(this[i], i, this[i]);
            // fn(i, this[i]);
        }
        // return this  - 链式编程核心
        return this;
    }

    // show() 显示
    Init.prototype.show = function () {
        // console.log('外面函数的this代表调用的JQ实例',this);
        // 遍历过程 - 隐式迭代核心
        this.each(function () {
            // console.log('内部函数的this变成了每一个元素 item',this)
            this.style.display = 'block';
        });
        // return this  - 链式编程核心
        return this;
    }

    // hide() 隐藏
    Init.prototype.hide = function () {
        // 遍历过程 - 隐式迭代核心
        return this.each(function () {
            this.style.display = 'none';
        });
        // return this  - 链式编程核心
        // return this;
    }

    // toggle() 切换
    Init.prototype.toggle = function () {
        return this.each(function () {
            // console.log(this)
            // debugger;
            // getComputedStyle() 获取计算样式,是否为 none
            if (window.getComputedStyle(this).display === 'none') {
                // 设置成变成默认值,因为 block 会直接改变显示模式,变成块级元素显示
                this.style.display = 'block';
            } else {
                this.style.display = 'none';
            }
        });
    }

})()

3、闭包:闭包其实就是一个局部变量作用域的延伸

闭包作用:

  • 没有形成闭包的量,会自动被垃圾回收清理掉。
  • 形成闭包的量就会被保留下来,当里函数调用的时候,会自动找到父级中的定义的量。
  • 形成闭包的局部变量可以被后续修改。
    在这里插入图片描述
    书写时形成闭包的情况
  1. 函数嵌套函数。
  2. 外函数定义了局部量。
  3. 里函数使用了外函数的局部量。
  4. 里函数能被调用了,里函数的代码运行。
var name = "The Window";
    var object = {
        name: "My Object",
        getNameFunc: function () {
            var that = this;            // 父级作用域下的 this,就是对象自己 object
            return function () {
                return that.name;       // that 是代表父级作用域下的 this,所以里面的代码相当于访问了 object.name
            };
        }
    };

    var res = object.getNameFunc();
    var LifnRes = res();
    console.log(LifnRes);       // "My Object"
  • 优点:使用闭包可以形成独立的空间,缓存数据,延长变量的生命周期
  • 缺点:延长了作用域链,需要释放的变量不能及时释放,可能引发内存泄漏

4、递归:程序在执行过程中不断调用自身

  • 递进:函数自己调用自己。
  • 回归:内部通过 return 回归,最终的回归条件记得写前面。

阶乘

 const fn = function (n) {
            if (n === 1) {
                return 1;
            }
            const result = n * fn(n - 1);
            return result;
        }
        const result = fn(4);
        console.log(result);

5、继承:原型继承,组合继承,类继承

  • 原型继承
// Person 构造函数
        const Person = function (name = '小明', age = 18, gender = '男') {
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        // run 的方法添加给了 Person 的构造函数
        Person.prototype.run = function () {
            console.log(this, '人能跑');
        }
        // Student 构造函数   Student 继承与 Person
        const Student = function (name = '学生老明', age = 58, gender = '男', number = 666) {
            Person.call(this, name, age, gender);
            this.number = number;
        }
        //  new Person() 创建一个人对象
        //  赋值给 Student.prototype  把创建的人实例,作为学生实例的父级
        Student.prototype = new Person();
        // 由于是赋值覆盖,所以 constructor 没有了,手动添加一下 constructor 属性
        Student.prototype.constructor = Student;

        Student.prototype.coding = function () {
            console.log(this, '学生能写代码');
        }


        const s1 = new Student();
        // console.log(s1);

        s1.coding();
        s1.run();
        console.log(s1.constructor);
  • 类继承
// 类语法 class
        class Person {
            // constructor 构造函数
            constructor(name = '人的名字', age = 0) {
                this.name = name;
                this.age = age;
            }
            // 方法自动添加到原型上,相当于 Person.prototype.run = function(){ }
            run() {
                console.log('人能跑');
            }
        }

        // 通过 extends 实现 类继承
        class Student extends Person {
            // constructor 构造函数
            constructor(name = '学生名字', age = 6, number = 666) {
                // 通过 extends 继承的类,constructor 构造函数内部必须调用一下 super()
                // super() 自动把 this 传递,自动把 name 和 age 传递,相当于 Person.call(this,name,age);
                super(name, age);
                this.number = number;
            }
            // 方法自动添加到原型上,相当于 Student.prototype.coding = function(){ }
            coding() {
                console.log('学生能写代码');
            }
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值