乐趣区

关于javascript:关于-JavaScript-中的方法的全部知识点都在这了

1. 什么是办法

首先让咱们定义并调用惯例函数:

function greet(who) {return `Hello, ${who}!`;
}

greet('World'); // => 'Hello, World!'

惯例函数定义 的模式为关键字 function 后跟名称、参数和函数体:function greet(who) {...}

greet('World') 惯例函数调用。函数 greet('World') 从参数承受数据。

如果 who 是对象的属性怎么办?要想轻松拜访对象的属性,能够将函数附加到该对象,也就是创立一个办法。

让咱们把 greet() 作为对象 world 的一个办法:

const world = {
  who: 'World',

  greet() {return `Hello, ${this.who}!`;  
  }
}

world.greet(); // => 'Hello, World!'

greet() { ...} 当初是属于 world 对象的一个 办法 world.greet() 是一种办法调用。

greet() 办法外部,this 指向该办法所属的对象 world。这就是为什么 this.who 表达式可能拜访属性 who 的起因。

this 也叫 上下文(context)

上下文是可选的

在上个例子中,咱们用了 this 来拜访该办法所属的对象,然而 JavaScript 并没有强制应用 this 的办法。

所以能够将对象作为办法的命名空间来应用:

const namespace = {greet(who) {return `Hello, ${who}!`;
  },

  farewell(who) {return `Good bye, ${who}!`;
  }
}

namespace.greet('World');    // => 'Hello, World!'
namespace.farewell('World'); // => 'Good bye, World!'

namespace 是一个领有 2 种办法的对象:namespace.greet()namespace.farewell()

这些办法没有用 this,而 namespace 是办法的所有者。

2. 对象字面量办法

如下面所示,你能够间接在对象字面量中定义方法:

const world = {
  who: 'World',

  greet() {return `Hello, ${this.who}!`;  
  }
};

world.greet(); // => 'Hello, World!'

greet(){....} 是在对象字面量上定义的办法。这种定义类型称为 简写办法定义(ES2015+ 开始可用)。

办法定义的语法也更长:

const world = {
  who: 'World',

  greet: function() {return `Hello, ${this.who}!`;  
  }
}

world.greet(); // => 'Hello, World!'

greet: function() {...} 办法定义。留神冒号和 function 关键字。

动静增加办法

办法只是一个函数,它作为属性被保留在对象上。因而能够向对象动静增加办法:

const world = {
  who: 'World',

  greet() {return `Hello, ${this.who}!`;
  }
};

// 一个带有函数的新属性
world.farewell = function () {return `Good bye, ${this.who}!`;
}

world.farewell(); // => 'Good bye, World!'

首先,world 对象没有 farewell 办法,它是被动静增加的。

调用动静增加的办法齐全没有问题:world.farewell()

3. 类办法

在 JavaScript 中,class 语法定义了一个类,该类是它实例的模板。

一个类也能够有办法:

class Greeter {constructor(who) {this.who = who;}

  greet() {console.log(this === myGreeter); // => true    
      return `Hello, ${this.who}!`;  
  }
}

const myGreeter = new Greeter('World');
myGreeter.greet(); // => 'Hello, World!' 

greet() {...} 是在类外部定义的办法。

每次应用 new 操作符创立类的实例时(例如,myGreeter = new Greeter('World')),都能够通过办法来创立实例。

myGreeter.greet() 是在实例上调用 greet() 办法的,办法外部的 this 等于实例自身,即 this 等于 greet() { ...} 办法外部的 myGreeter

4. 如何调用办法

4.1 办法调用

对象或类上定义方法只是实现了工作的一半。为了放弃办法的上下文,你必须确保将其作为“办法”去调用。

回忆一下带有 greet() 办法的 world 对象。让咱们检查一下当办法和惯例函数 greet() 被调用时,this 的值是什么:

const world = {
  who: 'World',

  greet() {console.log(this === world);    return `Hello, ${this.who}!`;
  }
};

// 办法调用
world.greet(); // => true
const greetFunc = world.greet;
// 惯例函数调用
greetFunc(); // => false

world.greet() 是一种办法调用。对象 world,后跟一个点 .,最初是办法自身,这就是 办法调用

greetFuncworld.greet 的性能雷同。然而当作为 惯例函数 greetFunc() 调用时,greet() 外部的 this 不等于 world 对象,而是等于全局对象(在浏览器中是 window)。

命名相似 greetFunc = world.greet 的表达式,将办法与其对象 离开。当稍后调用拆散的办法 greetFunc() 时,会使 this 等于全局对象。

将办法与其对象离开能够采取不同的模式:

// 办法是离开的!this 失落!const myMethodFunc = myObject.myMethod;

// 办法是离开的!this 失落!setTimeout(myObject.myMethod, 1000);

// 办法是离开的!this 失落!myButton.addEventListener('click', myObject.myMethod)

// 办法是离开的!this 失落!<button onClick={myObject.myMethod}>My React Button</button>

为防止失落办法的上下文,要确保应用办法调用 world.greet() 或将办法手动绑定到对象 greetFunc = world.greet.bind(this)

4.2 间接函数调用

在上一节中,惯例函数调用已将 this 解析为全局对象。那么有没有一种办法能够使惯例函数具备 this 的可自定义值?

能够应用上面的间接函数调用:

myFunc.call(thisArg, arg1, arg2, ..., argN);
myFunc.apply(thisArg, [arg1, arg2, ..., argN]);

myFunc.call(thisArg)myFunc.apply(thisArg) 的第一个参数是间接调用的上下文(this 的值)。换句话说,你能够手动扭转函数中 this 的值。

例如,让咱们将 greet() 定义为惯例函数,并定义一个具备 who 属性的对象 aliens

function greet() {return `Hello, ${this.who}!`;
}

const aliens = {who: 'Aliens'};

greet.call(aliens); // => 'Hello, Aliens!'
greet.apply(aliens); // => 'Hello, Aliens!'

greet.call(aliens)greet.apply(aliens) 都是间接办法调用。函数 greet() 中的 this 值等于 aliens 对象。

间接调用使你能够在对象上模仿办法调用。

4.3 绑定函数调用

最初是在对象上使函数作为办法调用的第三种办法:将函数绑定为具备特定上下文。

能够用非凡办法创立绑定函数:

const myBoundFunc = myFunc.bind(thisArg, arg1, arg2, ..., argN);

myFunc.bind(thisArg) 的第一个参数是函数要绑定到的上下文。

例如,让咱们重用 greet() 并将其绑定到 aliens 上下文:

function greet() {return `Hello, ${this.who}!`;
}

const aliens = {who: 'Aliens'};

const greetAliens = greet.bind(aliens);

greetAliens(); // => 'Hello, Aliens!'

调用 greet.bind(aliens) 会创立一个新函数,其中 this 绑定到 aliens 对象。

而后,当调用绑定函数 greetAliens() 时,this 等于该函数外部的 aliens

同样,应用绑定函数还能够模仿办法调用。

5. 箭头函数办法

不倡议将箭头性能用作办法,起因如下:

// 把 greet() 办法定义为箭头函数
const world = {
  who: 'World',

  greet: () => {return `Hello, ${this.who}!`;
  }
};

world.greet(); // => 'Hello, undefined!'

world.greet() 返回 'Hello, undefined!',而不是预期的 'Hello, World!'

问题是箭头函数内的 this 属于内部作用域,你想要 this 等于 world 对象,然而在浏览器中 thiswindow'Hello, ${this.who}!' 的计算结果为 Hello, ${windows.who}!,所以最初的后果是 'Hello, undefined!'

只管我很喜爱箭头函数,然而不能把它们用作办法。

总结

办法是属于对象的函数。办法的上下文(this值)等于该办法所属的对象。

你还能够在类上定义方法。类办法中的 this 等于实例。

仅定义一个办法是不够的,还要可能调用才行。个别办法调用实用以下语法:

// 办法调用
myObject.myMethod('Arg 1', 'Arg 2');

在 JavaScript 中,你能够定义一个不属于对象的惯例函数​​,而后将该函数作为对任意对象的办法来调用。你能够通过间接函数调用或将函数绑定到特定上下文来实现:

// 间接函数调用
myRegularFunc.call(myObject, 'Arg 1', 'Arg 2');
myRegularFunc.apply(myObject, 'Arg 1', 'Arg 2');

// 绑定函数
const myBoundFunc = myRegularFunc.bind(myObject);
myBoundFunc('Arg 1', 'Arg 2');


本文首发微信公众号:前端先锋

欢送扫描二维码关注公众号,每天都给你推送陈腐的前端技术文章


欢送持续浏览本专栏其它高赞文章:

  • 深刻了解 Shadow DOM v1
  • 一步步教你用 WebVR 实现虚拟现实游戏
  • 13 个帮你进步开发效率的古代 CSS 框架
  • 疾速上手 BootstrapVue
  • JavaScript 引擎是如何工作的?从调用栈到 Promise 你须要晓得的所有
  • WebSocket 实战:在 Node 和 React 之间进行实时通信
  • 对于 Git 的 20 个面试题
  • 深刻解析 Node.js 的 console.log
  • Node.js 到底是什么?
  • 30 分钟用 Node.js 构建一个 API 服务器
  • Javascript 的对象拷贝
  • 程序员 30 岁前月薪达不到 30K,该何去何从
  • 14 个最好的 JavaScript 数据可视化库
  • 8 个给前端的顶级 VS Code 扩大插件
  • Node.js 多线程齐全指南
  • 把 HTML 转成 PDF 的 4 个计划及实现

  • 更多文章 …
退出移动版