bind
bind/call/apply区别:
- bind将指定函数绑定执行的this,返回新的函数
- call和apply将调用函数绑定到指定this直接执行
- call和apply区别:传参不同,call将参数分开:fn.call(obj, ...args)
bind
- 作用:将一个函数绑定this,返回新的函数
- 调用:fn2 = fn1.bind(obj[, ...args])
- 入参:Object[, any]
- 返回:Function
- tip:需要分辨是否是new式调用,因为new式调用是走的另一套流程
const obj = {
name: 'hdy',
age: 19
}
function fn1(book, web) {
console.log(this.name);
console.log(book);
console.log(web);
}
const book = 'js红宝书';
const web = 'MDN';
const fn2 = fn1.bind(obj, book);
fn2(web);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 函数式调用
const obj = {
name: 'hdy',
}
function fn1() {
console.log(this.name);
return "对";
}
const fn2 = fn1.bind(obj);
const ans = fn2();
console.log(ans);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 类式调用不管用,因为类式调用应该走的是内部constructor方法的逻辑,this应该是被绑定到super传下来的this
const obj = {
name: 'hdy',
}
function fn1(age) {
this.age = age;
}
const fn2 = fn1.bind(obj);
const ans = new fn2();
console.log(ans);
console.log(ans.name);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 核心思想:
- 通过instanceof判断是否是new调用,然后分别绑定this
- 绑定原型链,保证new调用继承的属性不会丢失,同时作为instanceof识别是new调用的方式
new调用新function时,创建了新的对象,绑定了新的this,_ _ proto _ _指向新function的prototype。
那么bind也要保证原function的原型链不会断
Function.prototype.newBind = function (obj, ...args1) {
const _self = this;
const fn2 = function (...args2) {
if (this instanceof _self) {
return _self.call(this, ...args1, ...args2);
} else {
return _self.call(obj, ...args1, ...args2);
}
}
fn2.prototype = this.prototype;
return fn2;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const obj = {
name: 'hdy',
age: 18
}
function fn1(age) {
console.log(this.name);
console.log(age);
this.book = '蝴蝶书';
return "对";
}
const fn2 = fn1.newBind(obj);
const ans = fn2(11);
const n1 = new fn2(11);
console.log(ans);
console.log(n1);
console.log(obj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
call
call
- 作用:将函数绑定this执行
- 调用:fn.call(obj[, ...args])
- 入参:Object[, any]
- 返回:any
const obj = {
name: '张三',
age: 18
}
function fn() {
console.log(this);
console.log(this.age);
}
var age = 10
fn();
fn.call(obj);
1
2
3
4
5
6
7
8
9
10
11
12
13
apply
apply
- 作用:绑定函数执行的this执行
- 调用:fn.apply(thisArg[, [ ...args ]])
- 入参:Object[, Array | (类数组)]
- 返回:any
类Array:有下标做key,有length属性,如nodelist、arguments
const obj = {
name: 'hdy',
age: 18
}
const fn = function(book) {
console.log(`我的名字是${this.name},我今年${this.age}岁啦!我喜欢读${book}。`);
}
fn.apply(obj, ['蝴蝶书']);
1
2
3
4
5
6
7
8
9
length
length
- 作用:拿到function的形参数量
- 调用:fn.length
- 返回:Number
- tip:对形参解构无效
function fn1(name, age) {}
const fn2 = (name, age) => {}
console.log(fn1.length);
console.log(fn2.length);
1
2
3
4
5
function fn1(...args) {}
function fn2(name, ...args) {}
console.log(fn1.length);
console.log(fn2.length);
1
2
3
4
5
console.log(Function.length);
1
name
name
- 作用:查看函数名称
- 调用:fn.name
- 返回:String
function fn1() {}
const fn2 = () => {}
console.log(fn1.name);
console.log(fn2.name);
1
2
3
4
5
function People() {
if (!(this instanceof People)) {
console.log('禁止函数式调用类!')
}
}
People();
function Animal() {
if (this.__proto__.constructor.name !== 'Animal') {
console.log('禁止函数式调用类!')
}
}
Animal();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const obj = {
_name: 'hdy',
get name() {
return this._name;
},
set name(newName) {
this._name = newName;
}
}
const fn = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(fn.set.name);
console.log(fn.get.name);
1
2
3
4
5
6
7
8
9
10
11
12
13
toString
toString
- 作用:返回函数的定义代码
- 调用:fn.toString()
- 返回:String
function a() {}
const b = () => {}
console.log(a);
console.log(b);
1
2
3
4
5
arguments
arguments
- 作用:拿到函数实参
- 使用:函数内固有属性
- tip:箭头函数没有arguments
- tip:一般不建议直接用隐式对象,可以用...args显示调用
- tip:arguments是
类数组
,不是纯正的数组
function fn(a, b) {
console.log(arguments);
console.log(arguments.length);
}
fn('name', 18);
1
2
3
4
5
6
- 箭头函数没有arguments,nodejs全局环境有,所以可以读取到
const fn = () => console.log(arguments);
fn('name', 18);
1
2
3
const a = arguments;
const fn = () => console.log(arguments === a);
fn('name', 18);
1
2
3
4
5
6
7
function fn(a, b) {
console.log(arguments.length);
console.log(arguments instanceof Array);
Array.prototype.forEach.call(arguments, item => {
console.log(item);
})
}
fn('name', 'age');
1
2
3
4
5
6
7
8
9
10
箭头函数
箭头函数
- 作用:es6新增定义函数方式
- 使用:(...arg) => {}
- 特性:this/arguments/super/无法当构造函数
- 技巧:绑定this/匿名函数
const sum = (a, b) => a + b;
console.log(sum(1, 2));
1
2
3
const addOne = a => a + 1;
console.log(addOne(1));
1
2
3
const getPeople = (name, age) => ({name, age});
console.log(getPeople('hdy', 18));
1
2
3
const obj = {
name: 'hdy',
fn1() {
console.log(this.name);
},
fn2: () => console.log(this.name)
}
obj.fn1();
obj.fn2();
1
2
3
4
5
6
7
8
9
10
11
12
期望:
const obj = {
name: 'hdy',
age: 18
}
function fn1(book) {
this.book = book;
return this;
}
const fn2 = fn1.myBind(obj);
const a = fn2('红宝书');
console.log(a);
const b = new fn2('红宝书');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Function.prototype.myBind = function(obj, ...args1) {
const _self = this;
const fn = function (...args2) {
if (this instanceof _self) {
return _self.call(this, ...args1, ...args2);
} else {
return _self.call(obj, ...args1, ...args2);
}
}
fn.prototype = this.prototype;
return fn;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let callback;
callback = callback || function() {};
callback = callback || () => {};
callback = callback || (() => {});
1
2
3
4
5
6
7
new.target
new.target
- 作用:指向构造函数的应用
- 值:本Function的引用
- tip:只有new操作符才会被赋值,否则是undefined
function People(name) {
if (!new.target) {
throw Error('只能new调用此函数');
}
this.name = name;
}
const p1 = new People('hdy');
console.log(p1);
1
2
3
4
5
6
7
8
9
10
11
和this判断不同,this是拿到本function的实例对象
function A() {
console.log(new.target);
this.name = 'hdy';
}
function B() {
console.log(new.target);
A.call(this);
this.age = 18;
}
B.prototype.__proto__ = A.prototype;
const b = new B();
console.log(b);
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
constructor() {
console.log(new.target);
}
}
class B extends A {
constructor() {
super();
console.log(new.target);
console.log(this.constructor);
}
}
new B();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17