JavaScript apply 和 call 和 bind,原型和原型链的理解

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();
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值