new、apply、call、bind
JavaScript 中的 apply、call和 bind 方法是前端代码开发中相当重要的概念,并且与 this 的指向密切相关
new的实现
1、让实例可以访问到私有属性
2、让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性
3、构造函数返回的最后结果是引用数据类型
apply call
结合方法“借用”的原理
Function.prototype.call = function (context, ...args) {
let context = contextwindow;
context.fn = this;
var result = eval('context.fn(...args)');
delete context.fn
return result;
}
Function.prototype.apply = function (context, args) {
let context = context||window;
context.fn = this;
let result = eval('context.fn(...args)')
delete context.fn
return result;
}
这两个方法是直接返回执行结果而 bind 方法是返回一个函数因此这里直接用 eval执行得到结果
bind
bind 的实现思路基本和 apply 一样但是在最后实现返回结果这里bind 不需要直接执行,因此不再需要用 eval而是需要通过返回一个函数的方式将结果返回之后再通过执行这个结果,得到想要的执行效果
Function.prototype.bind = function (context, ...args) {
if (typeof this !== "function") {
throw new Error("this must be a function")
let self = this;
let fbound = function () {
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
if (this.prototype) {
fbound.prototype = object.create(this.prototype)
return fbound;
}
}
}
}
new
new 关键词的主要作用
就是执行一个构造函数、返回一个实例对象
根据构造函数的情况,来确定是否可以接受参数的传递
- 1.创建一个新对象
- 2.将构造函数的作用域赋给新对象(this 指向新对象)
- 3.执行构造函数中的代码(为这个新对象添加属性)
- 4.返回新对象
function Person() {
this.name = 'Jack'
}
var p = new Person();
console.log(p.name)
输出
Jack
new 关键词执行之后总是会返回一个对象要么是实例对象,要么是 return 语句指定的对象
apply & call& bind 原理介绍
call、apply和 bind 是挂在 Function 对象上的三个方法,调用这三个方法的必须是一个函数
三者的作用都是改变func的this指向。
A对象有个 getName 的方法,B 对象也需要临时使用同样的方法那么这时候可以借用 A对象的 getName 方法
let a = {
name: "jack",
getName: function (msg) {
return msg + " --- " + this.name
}
}
let b = {
name: "lili"
}
console.log(a.getName("hello"))
console.log(a.getName.call(b,"传奇"))
console.log(a.getName.apply(b,["DNF"]))
let name = a.getName.bind(b,"QQ飞车");
console.log(name())
输出:
hello --- jack
传奇 --- lili
DNF --- lili
QQ飞车 --- lili
应用场景
判断数据类型
用 Object.prototype.toString几乎可以判断所有类型的数据
function getType(obj) {
let type = typeof obj;
if (type !== "object") {
return type;
}
return Object.prototype.toString.call(obj).replace(/^$/, '$1')
}
console.log(getType(1))
输出:
number
类数组借用方法
let arrayLike = {
0: 'java',
1: 'script',
length: 2
}
Array.prototype.push.call(arrayLike, 'jack', 'lily')
console.log(typeof arrayLike);
console.log(arrayLike)
输出:
object
{ '0': 'java', '1': 'script', '2': 'jack', '3': 'lily', length: 4 }
获取数组的最大/最小值
用 apply 来实现数组中判断最大/最小值
apply 直接传递数组作为调用方法的参数
也可以减少一步展开数组
let arr = [13, 6, 10, 11, 16]
const max = Math.max.apply(Math, arr);
const min = Math.min.apply(Math, arr);
console.log(max);//16console.log(min);//16
console.log(min);//16console.log(min);//6
输出:
16
6