apply 和 call 改变 this 指向
apply 和 call 都可以让函数或方法调用
apply 第二参数是数组
call 参数是多个值
function f1(x,y){
return x+y
}
f1()
f1.apply(null,[10,20]) // 第一个参数是 改变的 this 指向
f1.call(null,10,20)
// 如果函数有返回值
let r1 = f1.apply(null,[10,20])
console.log(r1)
bind (复制) 也可以改变 this 指向
使用 bind 不能直接调用
function f1(x,y){
console.log((x+y))
}
// 复制
let r1 = f1.bind(null,10,20)
// 调用
r1()
// 或者如下 结果相同
let r1 = f1.bind(null)
r1(10,20)
原型
每个函数中有 prototype 属性 称之为原型,因为这个属性的值是一个对象,也称为原型对象
原型的作用
作用:存放属性和方法 目的是:节省内存空间
作用:实现继承 目的是:节省内存空间
原型链
对象中都有 proto 属性,指向构造函数的原型对象(prototype)(son.proto === Son.prototype),原型对象也有 proto 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链,最顶层找不到则返回 null
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sing = function () {
console.log("唱");
};
// 静态方法 只能用构造函数调用
Person.play = function () {
console.log('play');
}
Person.sex = '男'
Person.play() // play
console.log(Person.sex); // 男
function Son(name, age, sex) {
// 借用构造函数 --> 解决属性重复问题
Person.call(this, name, age);
this.sex = sex;
}
// 这种赋值形式,改变原型指向 --> 解决方法继承
Son.prototype = new Person();
// constructor 改回 Son 的指向构造函数
Son.prototype.constructor = Son;
const son = new Son("xm", 10, "男");
console.log("son", son);
// son.__proto__ === Son.prototype true
son.sing();
class
{
class Person {
// 构造方法,实例化时执行,this关键字则代表实例对象
constructor(username) {
this.username = username;
}
// 方法
getUsername() {
console.log(this.username);
}
}
const per = new Person("xr");
console.log(per.username); // "xr"
per.getUsername(); // "xr"
}
// 静态属性方法-直接通过类来调用,可继承
{
class Person {
static username = "zs";
// 此时 this 指的是类
static getUsername() {
// return Person.username;
return this.username;
}
}
const per = new Person();
console.log(Person.username); // "zs"
console.log(Person.getUsername()); // "zs"
class Student extends Person {
static fun() {
return this.getUsername() + super.getUsername();
}
}
console.log(Student.getUsername()); // "zs"
console.log(Student.fun()); // "zszs"
}
// 私有属性方法-只能在类的内部访问的方法和属性,不可继承
{
class Person {
#username = "#zs";
// 新写方法返回私有属性,变相实现继承
getUsername() {
return this.#username;
}
}
const per = new Person();
console.log(1, per.getUsername()); // "#zs"
}
// super这个关键字,既可以当作函数使用,也可以当作对象使用
// super作为函数调用时,代表父类的构造函数
// super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
{
class Person {
constructor(username) {
this.username = username;
}
play() {
console.log("per play");
}
}
class Student extends Person {
constructor(username, score) {
super(username);
this.score = score;
}
play() {
console.log("stu");
super.play();
}
}
const stu = new Student("xr", 66);
console.log(stu.score);
stu.play();
}