笔记目录
小概
本章学习内容:函数基本执行模式(普通函数调用,方法调用,构造函数调用) 了解函数/方法中的this指向;函数上下文调用模式(call(),apply(),bind()) 修改函数中的this指向;ES6类的介绍(类的创建,类添加方法,类的继承),super关键字的用法介绍。
1. 函数的基本执行模式
函数执行的三种方式:清楚函数中this的指向
- 普通函数调用
//1.普通函数调用.
//this就指向window对象.
function test(){
console.log('test函数');
console.log(this);
}
//test(); //相当于是window.test();
- 作为方法调用
let obj = {
name:'小斐',
age:18,
sayHi:function(){
console.log('你好');
console.log(this);
}
obj.sayHi(); //this指向调用者obj
谁调用这个方法/函数,那这个方法/函数中的this就是指向谁.
- 作为构造函数调用
function Student(name,age){
this.name = name;
this.age = age;
console.log(this);
}
let s2 = new Student('德华',21); //Student
Student('倩倩',23); //window.Student('倩倩',23);
不要管方法/函数是如何声明的,要看她是如何调用的,牢记谁调用这个方法/函数,这个函数/方法中的this就是谁.
2. 函数上下文调用模式
上述的三种执行方式是无法更改函数/方法中的this指向,所以需要使用到函数的第四种调用模式:函数上下文调用模式。
2.1 call()
语法:函数名。call(this的新指向,arg1,agr2…);
let obj = {
name: '广坤'
}
function getSum(num1,num2){
console.log(num1+num2);
console.log(this);
}
//getSum(10,20);
getSum.call(obj,100,200);
2.2 apply()
语法:函数名.apply(this的新指向,数组或者伪数组);apply方法只能传两个参数。
function getSum(num1, num2) {
console.log(num1 + num2);
console.log(this);
}
//getSum(10,20);
getSum.apply(obj,[30,40]); //依次的把数组的元素交给形参.
2.3 bind()
语法:函数名.bind(this的新指向[,arg1[,arg2…]])
注意:bind不会执行这个函数,而是返回一个this改变了而函数体一样的函数
function getSum(num1, num2) {
console.log(num1 + num2);
console.log(this);
}
//getSum(10,20);
let fn = getSum.bind(obj,10,20);//fn接收改变this指向的函数
fn(100,300);//调用
2.4 应用场景
需求:查找数组中的最大值/最小值
let arr = [1.,2,23,50,-10,];
let max = Math.max.apple(Math,arr);//把arr的每一个元素依次的交给max函数
需求:把伪数组转成真数组
let weiArr = {
0:'张三',
1:'李四',
2:'王五',
3:'陈麻子',
4:'狗蛋',
5:'狗剩儿',
length:6
}
//2. push();
// let arr = [];
// arr.push.apply(arr,weiArr); //把weiArr的每一项依次的交给push.
// console.log(arr);
//3. concat();
// let arr = [];
// arr = arr.concat.apply(arr,weiArr); //把weiArr的每一项依次的交给concat.
// console.log(arr);
//4. slice();
//如果weiArr可以调用数组的slice方法,那就会返回一个元素和weiArr一样的真数组,
//let arr = weiArr.slice(0);//但是很遗憾,weiArr不能调用数组的slice方法,所以这里报错了.
//那怎么办? 借用
// let arr = Array.prototype.slice.call(weiArr,0);
// console.log(arr);
//5.es6语法.
// let arr = Array.from(weiArr);
// console.log(arr);
需求:对元素都是数组的伪数组进行排序
let weiArr = {
0: 1109,
1: 110,
2: 220,
3: 215,
4: 210,
5: 500,
6: 400,
length: 7
}
//如果weiArr也能调用数组的sort方法,那就可以排序.
//但是他是伪数组,不能直接调用数组的sort方法.
Array.prototype.sort.call(weiArr,function(a,b){
return a-b;
});
console.log(weiArr);
2.5 组合继承
//组合继承.
function Person(name,age){
this.name = name;
this.age = age;
}
//替换Person的原型
Person.prototype = {
constructor:Person,
sayHi:function(){
console.log('你好,你吃了吗?');
}
}
//实例化一个人对象
let wangjianlin = new Person('王健林',58);
wangjianlin.house = {address:'东京',price:'1000000'};
console.log(wangjianlin);
//------------------------------------------------------------
function Student(name,age,score){
//借用构造函数继承
Person.call(this,name,age);
this.score = score;
}
//替换原型继承
Student.prototype = wangjianlin;
2.6 万能数据检测
万能数据类型检测
console.log(Object.prototype.toString.call(123));//'[object Number]'
console.log(Object.prototype.toString.call('abc'));//'[object String]'
3. ES6 类
3.1 类的创建
es6之前没有类的概念
class Student {
constructor(name,age,score){
this.name = name;
this.age = age;
this.score = score;
}
}
//实例化一个对象
let s1 = new Student('龙龙',18,100);
console.log(s1);
//再实例化一个对象
let s2 = new Student('伟哥',20,99);
console.log(s2);
//思考:
//es6中的类,本质就是es5中的构造函数.
console.log(typeof Student);//function
console.log(s1.__proto__ === Student.prototype);//true
console.log(s2.__proto__ === Student.prototype);//true
console.log(Student.prototype.constructor === Student); //true
注意:
1.声明类的时候,类名后面不要加小括号.
2.声明类的时候,类名首字母大写,类名也是一个名词.
3.用new关键字去实例化类的对象,会自动的调用constructor构造函数.
4.如果你声明类的时候,没有写constructor构造函数,那系统会自动的给你生成一个constructor构造函数.
3.2 类中添加方法
class Student {
constructor(name,age,score){
this.name = name;
this.age = age;
this.score = score;
}
study(kcName){
console.log('我是学生,我的名字是'+this.name+',我在学习'+kcName);
}
}
//往原型中添加一个方法
// Student.prototype.eat = function(){
// console.log('吃饭');
// }
// console.dir(Student.prototype);
3.3 类的继承
//创建一个学生类.
class Student {
constructor(name, age) {
this.name = name;
this.age = age;
}
study(kcName) {
console.log('我是学生,我的名字是' + this.name + ',我在学习' + kcName);
}
}
//创建一个大学生类 继承自 学生类
class CollegeStudent extends Student{
}
//实例化大学生对象.
let cs1 = new CollegeStudent('龙龙',19);
console.log(cs1);
cs1.study('金瓶梅');
//本质: 原型链继承
console.log(cs1.__proto__ === CollegeStudent.prototype);//true
console.log(cs1.__proto__.__proto__ === Student.prototype);//true
本质:原型链的继承
3.4 super关键字
super(); //调用父类的构造函数(构造器).
super.xx(); //调用父类的方法.
//创建一个大学生类 继承自 学生类
class CollegeStudent extends Student{
constructor(name,age,dx){
//就是在子类的构造器中一定要调用父类的构造器.并且这句话一定要写在子类构造器的第一句.
super(name,age);
console.log(this === that);//true
this.dx = dx;
}
}
//实例化大学生对象.
let cs1 = new CollegeStudent('龙龙',19,'蒋毅');
console.log(cs1);
如果子类constructor中需要新增属性,super()一定要写在子类构造器的第一句.
子类需要使用父类的方法:super.方法名().
注意:先写类,再用类实例化对象(写在类后面,不然会报错)。
总结
关键字:call,apply,bind;改变this指向,不同的环境用对应的关键字,call(指向对象,形参…)和apply(指向对象,[数组/伪数组])这两个修改this指向都会执行函数。bind则不会,但是bind会返回一个修改this指向后的函数,场景单击事件…
(子类)expends(父类) 类继承,super子类内部继承父类constructor/方法。
本文深入探讨JavaScript中的函数执行模式,包括普通函数、方法及构造函数调用,并介绍如何通过call、apply和bind改变函数上下文。此外,还讲解了ES6类的创建、方法添加及继承方式。

4万+

被折叠的 条评论
为什么被折叠?



