js高级总结

1.面向对象

1 面向过程和面向对象

  • 面向过程:关注的是过程中的每一步
    现实需求(吃蛋炒饭):开始→买鸡蛋→买米→炒蛋→蒸米…→蛋炒饭→ 结束
  • 面向对象:关注的是对象能做什么,找对象做事
    现实需求:(吃蛋炒饭): 老婆或老公或厨师做蛋炒饭(开始→买鸡蛋→买米→炒蛋→蒸米…→蛋炒饭→ 结束)
  • 注意:面向对象不是替代面向过程,而是对过程的高度封装。

2 如何面向对象编程

面向对象编程的概念:

​ Object Oriented Programming,简称 OOP ,是一种面向对象编程开发思想 。它将真实世界各种复杂的关系抽象为一个个对象 ,然后由对象之间分工合作,完成对真实世界的模拟。

① 真实世界各种复杂的关系:盖房子

② 抽象为一个个对象(找对象):找人,需要设计师、搬运工、砌墙师

③ 对象之间的分工:设计师设计图纸、搬运工搬砖,搬运材料、砌墙师砌墙

④ 对象之间的合作:搬运工搬砖给砌墙师用

⑤ 完成

面向对象编程的步骤:(重点)

  1. 明确需求
  2. 划分对象
  3. 对象分工
  4. 对象合作
  5. 完成目标

3 面向对象的好处

  • 适合大型项目的开发,提高开发效率
  • 易于维护。

4 面向对象的特征

  • 封装:把过程封装到对象中
  • 继承:子承父业。减少代码冗余(减少代码量)
  • [多态]:一种事物(动物),具有多种形态(一条狗、一只猫…)。

二、类和对象

1 什么是类

  • 生活中:一类、种类
  • 编程中
    • 类指的是抽象的名称:狗
    • class关键字,ES6之前没有类的概念。 我们现在学的是ECMAScript3和ES5
    • 在ES3或ES5中通过构造函数 来创建对象
    • 构造函数:
      • 内置的:Object、Date、Array等
      • 自定义:Dog
    • 总结:现阶段我们通过构造函数 来创建对象
    • new关键字

2 什么是对象

  • 生活中:万物皆对象。任何具体的事和物都可以看成对象
  • 编程中:对象由属性方法组成(或由键值对)。 具体的实例,实例对象
    • 属性:对象的静态特征,咱们班的班长,姓名、年龄、身高、性别
    • 方法:对象的功能特征,咱们班的班长,点名、写代码
    • 注意事项:
      • 方法的值用什么表示,用函数来表示
      • 对象方法中的this,指向调用者。

3 类(构造函数)和对象的关系

  • 类是对象的模板
  • 对象是类的具体实例(通过关键字 instanceof 检测一个对象是否属于某一个类型)
    • 语法:对象名 instanceof 构造函数名; 返回布尔值
  • 创建对象得通过类(构造函数)创建
  • new 构造函数() → 具体的实例
  <script>
    // 类: Object 构造函数 → 类 → 抽象的名词
    // 对象:new Object() 或 {} → 实例对象→ 具体的实例
    // 对象组成:属性和方法
    // 类和对象的关系:对象是类的一个实例,(对象属于类)
    var obj = {
      // 属性
      name:'张三',
      age:10,
      // 方法
      eat:function(){
        alert('我会吃....')
      },
      sayHi:function(){
        // 方法中的this指向调用者
        console.log('我叫' + this.name)
      }
    };

    obj.sayHi();


    // obj的构造函数是 Object
    console.log(obj instanceof Object);
  </script>

4 创建对象

  • 语法:自定义构造函数

    function 构造函数名(参数...){
        this.key = value;
        .......
    }
    // 注意规范:构造函数名首字母要大写  帕斯卡(每个单词首字母大写)  驼峰(从第二个单词开始首字母大写)
    
  • 语法:new关键字创建对象

    var 对象名 = new 构造函数名(实参...);
    

5 new关键字的执行过程

  1. 在内存中创建一个空对象
  2. this指向创建的对象
  3. 向这个空对象中添加属性和方法
  4. 返回当前的对象(默认返回值就是当前创建的对象)

6.构造函数和普通函数

  • 相同点
    • 都是函数
  • 不同点
    • 构造函数通过new关键字调用
    • 普通函数直接调用
  <script>
    // 需求:每一个学生会自我介绍(叫什么、多大了)、敲代码、唱歌
    // 对象有什么属性?  姓名和年龄
    // 对象有什么方法?  自我介绍、敲代码、唱歌
    
    // 定义构造函数
    function Student(name,age) {
      // 属性
      this.name = name;
      this.age = age;
      // 方法
      this.sayHi = function(){
        console.log('我叫' + this.name + ',今年' + this.age);
      }
      this.writeCode = function(){
        console.log('我会编程!');
      }
      this.sing = function(){
        console.log("我会唱歌")
      }
    }
  

    // 创建对象
    // 一个函数是普通函数还构造函数,不是在定义时决定的,而是在调用时决定
    // Student();  → 普通函数
    var stu1 = new Student('张三',10);  // → 构造函数  

    // 使用对象→ 使用对象的属性或使用对象的方法
    stu1.sayHi();
  </script>

三、原型

1.为什么要学习原型

  • 前提:对象在内存中占据空间。对象的成员的数量可以决定对象在内存中占据空间的大小。
  • 在对象中,属性一般是变化的。 方法都是function,是不变的。
  • 问题:对象的方法是不变的,每创建一个对象,都要存放3个方法,创建多个对象时,相对而言,会消耗内存。
  • 原因:对象的方法是不变的
  • 解决:想办法把不变的方法,抽取出来放在【原型】,让同类型的的对象共享即可。

2.什么是原型

  • 原型就是一个对象,原型一直都在。
  • 获取原型:
    • 语法:构造函数名.prototype
<body>
  <script>

    // 定义构造函数
    function Student() {
      // 属性
      this.name = name;
      this.age = age;
    }

    // 原型是一个对象,本来就有。
    // 每定义一个函数,系统会为其分配一个原型
    // 获取原型:函数名.prototype。 原型内部默认有一个constructor,指向对应的构造器→ 构造函数
    var yx = Student.prototype;
    console.log(yx);
    // console.log(yx.constructor === Student);  //true



    
  </script>
</body>

3.构造函数和原型的关系

理论

  • 构造函数可以通过 prototype 获取到原型
  • 原型可以通过 constructor 找到构造函数
 <script>

    // 【定义构造函数】
    function Student(name, age) {
      // 属性
      this.name = name;
      this.age = age;
    }

    // 【使用原型】
    var yx = Student.prototype;
    // 把方法添加到原型中。 对象.key = value;
    // 方法
    yx.sayHi = function () {
      console.log('我叫' + this.name + ',今年' + this.age);
    }
    yx.writeCode = function () {
      console.log('我会编程!');
    }
    yx.sing = function () {
      console.log("我会唱歌")
    }

    // 【创建对象】
    // 创建第1个学生对象
    var zs = new Student('张三', 10);
    // 创建第2个学生对象
    var ls = new Student('李四', 12);
    // 创建第3个学生对象
    var ww = new Student('王五', 20);
  </script>

4 原型的作用

  • 节省内存。 因为原型中存放的成员(属性或方法),都可以被相关的构造函数所创建的对象共享

5 实例对象和原型的关系

理论

  • // ① 首先,会从对象本身中去找
  • // ② 若对象中,找不到,则会通过__proto__所提供的原型地址,找原型
  • // ③ 去原型中查找。
  <script>

    // 【定义构造函数】
    function Student(name, age) {
      // 属性
      this.name = name;
      this.age = age;
    }

    // 【使用原型】
    var yx = Student.prototype;
    // 把方法添加到原型中。 对象.key = value;
    // 方法
    yx.sayHi = function () {
      console.log('我叫' + this.name + ',今年' + this.age);
    }
    yx.writeCode = function () {
      console.log('我会编程!');
    }
    yx.sing = function () {
      console.log("我会唱歌")
    }

    // 【创建对象】
    // 创建第1个学生对象
    var zs = new Student('张三', 10); 
    // zs.sayHi();
    // zs.sing();
    // console.log(zs);
    console.log(zs)

    // 对象在去访问或调用一个成员(属性或方法)时,过程是这样的:
    // 1. 先从对象自身查找,若查找不到
    // 2. 则会通过系统分配的__proto__(原型的地址)找到原型,去原型中查找要访问或调用成员
  </script>

image

6.认识object

 <script>
    // 第一个构造函数:Object
    // 祖宗类
    // 在js中任何类型的对象,都属于Object
    // Object 是构造函数
    // Object.prototype

    console.log(document instanceof Object);
    console.log(console instanceof Object);
    var arr = new Array();
    console.log(arr instanceof Array);
    console.log(arr instanceof Object);
  </script>

7.原型链

image
image

四、继承介绍

1 什么是继承?

  • 生活:子承父业
  • 编程:类与类之间的关系。 子类继承父类中的成员。
    • 不用继承:
      • 学生类:姓名、年龄、性别、打招呼、跑
      • 医生类:姓名、年龄、性别、打招呼、跑
      • 老师类:姓名、年龄、性别、打招呼、跑
    • 使用继承:
      • 人类[父类]:姓名、年龄、性别、打招呼、跑
      • 学生类[子类]→人类[父类]
      • 医生类[子类]→人类[父类]
      • 老师类[子类]→人类[父类]

2 继承的作用

减少代码或简化代码。

五、原型继承

1.如何实现原型继承?

  • 先更改子类的原型prototype指向一个new 父类() 对象。
    • 子类.prototype = new 父类();
  • 再给子类的原型设置一个constructor指向子类
    • 子类.prototype.constructor = 子类
  • 然后用子类构造函数new出来的实例对象就可以调用原型继承的方法
   <script>
    // 【人类】- 父类
    function Person() {
      // 属性
      this.name = '姓名';
      this.age = 10;
      this.gender = '男';
    }
    Person.prototype.sayHi = function () {
      console.log('我叫' + this.name);
    }
    Person.prototype.run = function () {
      console.log('我会跑~~~');
    }
    // 【学生类】-子类→继承人类
    function Student() {
      this.stuId = '1111';
    }
    // ① 更改子类构造函数的prototype指向父类的一个具体实例
    Student.prototype = new Person();
    // ② 为了更加完善,在父类的实例对象中添加一个constructor指向子类
    Student.prototype.constructor = Student;
    // 创建一个学生对象
    var stu = new Student();
    console.log(stu);
  </script>

2.优缺点

优点:完美继承了方法

缺点:无法完美继承属性

六、借用继承

1 call方法

  • 语法:函数名.call(调用者,函数实参,函数的实参...);
  • 作用:该函数会立即执行,函数体内的this在被call时,this指向调用者
  <script>
    // 函数
    function Person(name,age,gender) {
      console.log(this===obj);
      this.name = name;
      this.age = age;
      this.gender = gender;
    }

    // 调用函数0
    // Person('张三',10,'男');
    // 普通函数内部this默认指向window


    // 【需求】:在调用执行Person时,更改函数内部this指向obj,实现把name、age、gender添加到obj中
    var obj = {};
    // 想办法实现Person函数内部this指向obj
    // 实现方式:函数名.call(调用者,函数实参,函数的实参...)
    // 在这一次调用时,函数内部this指向obj
    Person.call(obj,'张三',10,'男');
    
  </script>

2 使用call实现借用继承******

如何实现:

  • 在子类中,通过call调用父类,并更改父类中this的指向子类对象。
  <script>
    // 【人类】- 父类
    function Person(name,age,gender) {
      // 属性
      this.name = name;
      this.age = age;
      this.gender = gender;
    }
    Person.prototype.sayHi = function () {
      console.log('我叫' + this.name);
    }
    Person.prototype.run = function () {
      console.log('我会跑~~~');
    }

                                                        
    // 【学生类】-子类→继承人类
    function Student(name,age,gender,stuId) {
      // 在被new时,在Student中的this指向当前创建的对象 stu、stu2
      this.stuId = stuId;
      // var obj = this;
      // 借用
      // Person.call(obj,name,age,gender);
      // 把this放在这里,相当于把要给学生的实例对象的地址放在这里
      Person.call(this,name,age,gender);
    }


    // 创建一个学生对象
    var stu = new Student('张三',10,'男',10086);
    // 创建一个学生对象
    var stu2 = new Student('李四',20,'女',10010);


    // 结论:如何实现借用继承
    // 在子类构造函数中,使用call语法方式借用父类函数,更改父类函数中this指向子类的一个实例对象
    // 语法:父类函数名.call(子类实例,实参,实参....)
  </script>

优缺点:

​ // 优点:完美继承了属性

​ // 缺点:无法继承方法。

七、组合继承

如何实现

原型继承和借用继承同时使用。

  <script>
    // 【人类】- 父类
    function Person(name,age,gender) {
      // 属性
      this.name = name;
      this.age = age;
      this.gender = gender;
    }
    Person.prototype.sayHi = function () {
      console.log('我叫' + this.name);
    }
    Person.prototype.run = function () {
      console.log('我会跑~~~');
    }


    // 【学生类】-子类→继承人类
    function Student(name,age,gender,stuId) {
      this.stuId = stuId;
      // 【借用继承】
      Person.call(this,name,age,gender);
    }
    // 【原型继承】
    Student.prototype = new Person();
    Student.prototype.constructor = Student;


    // 创建一个学生对象
    var stu1 = new Student('张三',10,'男',10086); 
    // 创建一个学生对象
    var stu2 = new Student('李四',20,'女',10010);
   </script>

八、函数内部this的指向

  • this在函数中指向谁,不是在定义函数时决定的,而是在调用函数时决定的。

1 普通函数中this的指向

  • this指向window
  // 【在普通函数中this指向window】
 function fn() {
 console.log(this);
}
 fn()
 
 
   var fn = function() {
      console.log(this);
    };
    fn();

    (function(){
      console.log(this);
    })();


    function fn1() {
      function fn2() {
        console.log(this);
      }
      fn2();
    }
    fn1();

2.定时器中this的指向

  • this指向window
   // 【在定时器中this指向windnow】
    setTimeout(function(){
      console.log(this);
    },1000);
    setInterval(function(){
      console.log(this);
    },1000);

3 构造函数中this指向

  • this指向当前创建的对象-在内存中开辟的空间
  // 【在构造函数中this指向当前创建的对象】
    // 要通过new关键字执行过程理解
    function Student(name, age) {
      this.name = name;
      this.age = age;
    }

    Student.prototype.sayHi = function () {
      console.log('我叫' + this.name);
    };

    var stu1 = new Student('张三', 10);
    var stu2 = new Student('李四', 10);

4.方法中this指向

  • 对象.方法名(); 指向调用者
 // 【在方法中,this指向调用者。  对象.方法()】
    stu1.sayHi();
    stu2.sayHi();

5 事件处理程序中this指向

  • this指向事件源
    // 【在事件处理程序中,this指向事件源】
    document.onclick = function () {
      console.log(this);
    };

九、改变this的指向

1 call方法

  • 语法:函数名.call(调用者,参数1…)
  • 作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者或调用者
    function fn(name, age) {
      this.name = name;
      this.age = age;
    }

    // 对象字面量
    var obj = {};
    fn.call(obj, '李四', 11);

2 apply方法

  • 语法:函数名.apply(调用者,[参数1…])
  • 作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者或调用者
  function fn(name, age) {
      this.name = name;
      this.age = age;
    }

    // 对象字面量
    var obj = {};
    fn.apply(obj, ['李四', 11]);

3 bind方法

  • 语法:函数名.bind(调用者,参数1…)
  • 作用:函数被借用时,不会立即执行,而是返回一个新的函数。需要自己手动调用新的函数
    function fn(name, age) {
      this.name = name;
      this.age = age;
    }

    // 对象字面量
    var obj = {};
    fn.bind(obj, '李四', 11);
<body>
  <script>
    // 函数
    function fn(a, b) {
      this.a = a;
      this.b = b;
    } 
    // 对象
    var obj = {};
    // 需求: 在调用时,更改函数fn内部this指向obj

    // 【call方法】
    // - 语法:函数名.call(呼叫者,参数1...) 
    // - 作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者或呼叫者
    // fn.call(obj,100,200);

    // 【apply方法】
    // - 语法:函数名.apply(呼叫者,[参数1...]) 
    // - 作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者或呼叫者
    // fn.apply(obj,[300,600]);

    // 【bind方法】
    // - 语法:函数名.bind(呼叫者,参数1...) 
    // - 作用:函数被借用时,不会立即执行,而是返回一个新的函数。需要自己手动调用新的函数
    // 接收新的函数
    var newFn = fn.bind(obj,1000,2000);
    // 直接调用
    newFn();
    // fn.bind(obj,10000,50000)();
  </script>
</body>

十、函数的其他成员

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值