js高级知识点整理

**js高级知识点整理

  • 实例对象中有一个属性叫__proto__, 叫原型, 也是对象.这个属性是浏览器使用, 不是标准的属性
    构造函数中有一个属性叫prototype, 叫原型, 也是对象, 这是属性是程序员使用的,才是标准的属性
    实例对象的__proto__和构造函中的prototype相等
    又因为实例对象是由构造函数创建的
    所以 实例对象的__proto__ 指向了构造函数中的原型对象

    1.通过原型添加方法

//需求: 点击换颜色
    //1.体会面向过程
    // document.getElementById("btn").onclick = function () {
    //     document.getElementById("box").style.backgroundColor = "red";
    // }
    //面向对象的思想
    // 操作谁, 按钮, div, 换颜色
    function Style(btnId, boxId, color) {
        this.btnId = document.getElementById(btnId);
        this.boxId = document.getElementById(boxId);
        this.color = color;
    }
    //在原型中添加方法-----共享数据, 节省空间
    Style.prototype.init = function () {
        console.log(this);//指向的实例对象
        var that = this;
        //当函数嵌套时, this指向会发生变化. 解决: 使用变量储存
        //点击按钮换颜色
        console.log(this.btnId);
        this.btnId.onclick = function () {
            console.log(this.btnId);//this指向有问题
            that.boxId.style.backgroundColor = that.color;
        }
    }
    //实例化对象-----创建对象并初始化
    var changeColor = new Style("btn", "box", "green");
    var changeColor2 = new Style("btn1", "box1", "blue");

    changeColor.init();
    changeColor2.init();
    console.log(changeColor);
2.简单的原型写法---缺少构造器
function Student(name, score) {
        this.name = name;
        this.score = score;
    }
    Student.prototype = {
        //手动添加构造器
        constructor: Student,
        height:"180mm",
        weight: "70kg",
        study: function () {
            console.log("学习使我快乐, 我要每天写5000行代码");
        }
    }

    var stu1 = new Student("徐小小", "59分");
    stu1.study();
    console.dir(stu1);

3.//找属性, 先从实例对象中获取, 如果找不到, 去构造函数的原型对象上面去找

    function Person(name, sex) {
        this.name = name;
        //this.sex = sex;
    }
    Person.prototype.sex = function () {
        console.log("女");
        return "女";
    };
    var per1 = new Person("小明", "男");
    console.dir(per1);
    var result = per1.sex();
    console.log(result);
    console.log(per1.sex());//

4.为内置对象添加方法—使用原型

 //需求: 在字符串中有一个倒序字符串的方法
    var string = new String();
    String.prototype.daoStr = function () {
        var ss = '';
        for(var i = this.length - 1; i >= 0 ; i--){
            ss += this[i];
        }
        return ss;
    }
    var str2 =  new String("123456789");
    console.log(str2.daoStr());
    console.dir(str2);

5.局部变量变成全局变量

 // 局部变量 变成 全局变量:  把局部变量暴露给window
    //浏览器的顶级对象是: window
    //js是一门动态类型语言
    (function () {
        var num = 10;
        window.number = num;
    })();
    console.log(window.number);//window可以省略
    console.log(number);//window可以省略
  • 原型和原型链
    原型链: 是实例对象和原型对象之间的关系. 是__proto__原型来链接的

    1.原型链最终指向哪里?

function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.eat = function () {
        console.log("六一要吃棒棒糖")
    }
    var per = new Person("徐小小","12岁");
    per.__proto__.eat();
    console.dir(per);
    console.dir(Person.prototype.__proto__);// object
    console.log(Object.prototype.__proto__);//Object是系统的构造函数, 里面就应该有prototype.又是对象, 那么对象里就应该有__proto__, 最终这个会指向null
    var obj = new Object();

2.原型指向能不能改变

 function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.eat = function () {
        console.log("六一要吃棒棒糖")
    }
    var per = new Person();
    function Student() {

    }
    Student.prototype.study = function () {
        console.log("六一要学习")
    }
    Student.prototype = new Person();//学生的原型, 指向了人的对象
    var stu = new Student();
    //他们之间没有任何.   想让他们有关系
    //stu.study();//报错了
    stu.eat();//能访问到. 因为指向已经改变. 所以能访问到人对象的方法
    // 所以原型指向可以改变

3.原型指向改变后如何添加方法

function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype = {
        play: function () {
            console.log(this)
        }
    }
    Person.prototype.eat = function () {
        console.log(this)
        console.log("六一要吃棒棒糖")
    }
    var per = new Person();
    per.eat();//不报错  等会解释
    per.play();
    // 1.所以原型指向可以改变
    // 2.原型指向改变后再添加方法

4.继承: 是一种关系,父类与子类的继承关系. 通过原型来实现继承. 继承也是为了数据共享(四种方法)

4.1 * .原型继承: 改变原型的指向

 * 例子:
    *--> 小明 有钱, 有名字, 有功夫
    *       儿子-->小小明. 继承钱, 继承功夫, 继承姓氏
    * */
    function Person(name, money) {
        this.name = name;
        this.money = money;
    }
    Person.prototype.play = function () {
        console.log("咏春 , 叶问")
    }
    var per = new Person("小明","100块")
    function SmallPer(score) {
        this.score = score;
    }
    SmallPer.prototype = new Person("小小明", "1块");
    SmallPer.prototype.study = function () {
        console.log("学习")
    }
    var xiaoxiaoming = new SmallPer("99分")

    console.log(xiaoxiaoming.name, xiaoxiaoming.money, xiaoxiaoming.score);
    xiaoxiaoming.study();
    xiaoxiaoming.play();

4.2.借用构造函数继承: 改变构造函数属性的指向
为了数据共享.改变原型指向. 坐到了继承, 但是继承过来的属性值也是一样的.
改善方法:继承的时候不改变原型的指向. 直接调用父级的构造函数的方式来赋值. 叫借用构造函数

function Person(name, money) {
        this.name = name;
        this.money = money;
    }
    Person.prototype.play = function () {
        console.log("咏春 , 叶问")
    }
    function Student(score, name, money) {
        this.score = score;
        //把父亲的构造函数借过来--->改变构造函数的指向, 继承属性
        Person.call(this,name, money)
        //this指的是当前函数的所创建出来的对象, 后面的参数是父亲的形参. 这个形参学生要用, 所以需要学生的构造函数的小括号接收一下;
    }
    var stu1 = new Student("33分","小明", "1块钱");
    var stu2 = new Student("99分","小红", "99块钱");
    console.log(stu1.name, stu1.score, stu1.money);
    console.log(stu2.name, stu2.score, stu2.money);
    stu1.play();//此时会报错
    stu2.play();//此时会报错

4.3.组合继承: 原型继承 + 借用构造函数继承. 既能解决属性问题, 又能解决方法问题

function Person(name, money) {
        this.name = name;
        this.money = money;
    }
    Person.prototype.play = function () {
        console.log("咏春 , 叶问")
    }
    function Student(score, name, money) {
        this.score = score;
        //把父亲的构造函数借过来--->改变构造函数的指向, 继承属性
        Person.call(this,name, money)
        //this指的是当前函数的所创建出来的对象, 后面的参数是父亲的形参. 这个形参学生要用, 所以需要学生的构造函数的小括号接收一下;
    }
    //改变原型指向继承方法
    Student.prototype = new Person();
    var stu1 = new Student("33分","小明", "1块钱");
    var stu2 = new Student("99分","小红", "99块钱");

    console.log(stu1.name, stu1.score, stu1.money);
    console.log(stu2.name, stu2.score, stu2.money);
    stu1.play();
    stu2.play();
  • 4.拷贝继承: 就是把对象中需要共享的属性和方法, 以遍历的方法复制到另一个对象
    //拷贝继承: 就是把对象中需要共享的属性和方法, 以遍历的方法复制到另一个对象
function Person() {

    }

    Person.prototype.name = "lucy";
    Person.prototype.sex = "boy";
    Person.prototype.play = function () {
        console.log("rap rap go go go");
    }
    var obj2 = {}
    for(var key in Person.prototype){
        obj2[key] = Person.prototype[key];
    }
    console.log(obj2);
  • this指向的改变
    1.call(this,参数1,参数2…参数n);
    用法说明:①不传参数1, 或者只传一个null, 那么this还是 默认的window
 function f1(x,y){
        console.log(x+y,this);
    }
    f1(10,20);
    f1.call(null,10,30);
    f1.apply(null,[10,30]);

效果图
在这里插入图片描述
②传参数1,但参数1不等于null时,this指向传入的参数1所对应的对象

function f1(x,y){
        console.log(x+y,this);
    }
    var obj={
        age:19,
        sex:"男"
    }
    f1.call(obj,10,30);

效果图
在这里插入图片描述
2.apply(this,参数1,参数2…参数n);
用法说明:①不传参数1, 或者只传一个null, 那么this还是 默认的window

function f1(x,y){
        console.log(x+y,this);
    }
    f1.apply(null,[10,30]);

效果图
在这里插入图片描述
②传参数1,但参数1不等于null时,this指向传入的参数1所对应的对象

 var obj={
        age:19,
        sex:"男"
    }
    f1.apply(obj,[10,30]);

效果图
在这里插入图片描述
3.bind(this,参数1,参数2…参数n)只是绑定this,不是调用的时候改变this
用法说明:①不传参数1, 或者只传一个null, 那么this还是 默认的window

    function f1(x,y){
        console.log(x+y,this);
    }
    var ff=f1.bind(null,10,20);//此时bind方法相当于复制了一份返回值给某个对象
    console.log(ff);
    console.log(ff());
    //var ff=f1.bind(null);
    // console.log(ff(10,20));//可以在复制的时候传入参数,也可以在复制之后传参

效果图
在这里插入图片描述
②传参数1,但参数1不等于null时,this指向传入的参数1所对应的对象

 function f1(x,y){
        console.log(x+y,this);
    }
    function Person(name,age){

    }
    Person.prototype.eat=function(){
        console.log("吃");
    };
    var per=new  Person();
    var fff=f1.bind(per);
    fff(10,20);
    var ff=f1.bind(per);
    ff(100,200);

效果图
在这里插入图片描述
总结: 1.使用一个函数需要改变this指向
1.1.传递的参数不多,使用fn.call(需要指向的对象,参数1,参数2…)
1.2.传递的参数教多,使用fn.apply(需要指向的对象,[参数1,参数2…])
1.3.只想将函数长期的绑定给某一个对象使用fn.bind(需要指向的对象,参数1,参数2…)

  • 函数
    1.函数的几个参数
function f1(x, y) {
        console.log(f1.arguments.length);//实参的个数
        console.log(f1.length);//形参的个数
        console.log(f1.name);//函数名
        console.log(f1.caller);//f1的调用者是f2
    }
    f1.name = "fff";//不能修改
    f1(10, 20, 30, 40);
    function f2() {
        f1(1,2)
    }
    f2();
   console.dir(f1);

2.高阶函数之函数作为参数

function f1(fn) {
        fn();
    }
    //传匿名函数
    f1(function () {
        console.log("我是匿名函数");
    });
    //传有名函数
    function f3() {
        console.log("我是有名函数");
    }
    f1(f3);//f3不要带小括号

3.高阶函数之函数作为返回值

 function f1() {
        console.log("f1函数的开始");
        return function () {
            console.log("哈哈哈哈");
        }
    }
    var ff = f1();
    console.log(ff);
    ff();

4.*闭包
闭包的概念: 函数a中, 有一个函数b, 函数b可以读取函数a中定义的变量. 就形成了闭包
闭包就是将函数内部和函数外部链接起来的桥梁
闭包的作用: 缓存数据, 延长作用域链
优点及缺点: 缓存数据,延长作用域链(缺点: 就是因为缓存数据,导致变量不能及时的释放, 延长了作用域链)

//函数的闭包
    // function f1() {
    //     var num = 10;
    //     function f2() {
    //         console.log(num);
    //     }
    //     f2();
    // }
    // f1();
    //
    // //对象的闭包
    // function ff() {
    //     var age = 30;
    //     return {
    //         age:age
    //     }
    // }
    // var result = ff();
    // console.log(result.age);

闭包的练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>点赞案例</title>
    <style>
        ul {
            list-style-type: none;
        }
        li {
            float: left;
            margin-left: 10px;
        }

        img {
            width: 200px;
            height: 180px;
        }

        input {
            margin-left: 30%;
        }
    </style>
</head>
<body>
<ul>
    <li><img src="images/1.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
    <li><img src="images/2.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
    <li><img src="images/3.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
    <li><img src="images/4.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
</ul>
<script>
    var btns = document.getElementsByTagName("input");
    for (var i = 0 ; i < btns.length ; i++) {
        //var index = 1;
        btns[i].onclick = getValue();
    }

    function getValue() {
        var index = 1;
        return function clickHandle() {
            this.value = "赞(" + (++index) + ")";
        }
    }
</script>
</body>
</html>

5.沙箱-----函数的自调用
//沙箱: 独立, 虚拟的环境. 可以在环境中模拟真实的世界. 所做的实验结果和真实的世界的结果是一样的, 但是不会影响

    var num = 10;
    //这就是沙箱环境
    (function () {
        var num = 100;
        console.log()
    })();
    console.log(num);

6.递归: 函数中调用自己

//求斐波那契数列  1、1、2、3、5、8、13, 21, 34,55, 89, 144
    function getFib(x) {
        if(x == 1 || x == 2){
            return 1;
        }
        //后一个数 = 前两个数的和
        return getFib(x - 1) + getFib(x - 2);
    }
    console.log(getFib(12));
  • cookie : 用于储存页面的用户信息
  • 例子: 自动登录, 记住用户名
    • 特征: 1. 同一个网站的所有页面共享一套cookie
    •   2. 数量大小有限 一般是4k . 只能文本 1m = 1024k, 1k = 1000多个字节(字母)或者500多汉字
      
    •   3.有过期时间 ①临时性质的 cookie ②设置失效的时间的cookie
      
    • */
    • 1.临时的cookie
    //1.在文档中创建cookie   document.cookie = "名字=值"; 以键值对的方式来写
    //①创建临时cookie----->关闭浏览器消失, 跟注释没关系
    //document.cookie = "username1=张三";
    //alert(document.cookie);

2.有失效时间的cookie

  //②设置失效的时间的cookie(3天之后过期) document.cookie = "名字=值;expires=过期时间";
    var dt = new Date();
    //设置日期  setDate()
    dt.setHours(dt.getHours() - 8);//获得的时间是国际时间,和我国相差八小时
    dt.setMinutes(dt.getMinutes() + 1);
    //console.log(dt);
    // document.cookie = "username=胡小歌;expires="+dt;
    // document.cookie = "username1=霍建华;expires="+dt;
    // document.cookie = "username2=彭于晏;expires="+dt;
    //document.cookie = "username3=彭于晏;expires="+dt;
    alert(document.cookie);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值