From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../global_objects/function/apply/index.html | 219 ++++++++++++++ .../global_objects/function/arguments/index.html | 125 ++++++++ .../global_objects/function/arity/index.html | 16 + .../global_objects/function/bind/index.html | 324 +++++++++++++++++++++ .../global_objects/function/call/index.html | 174 +++++++++++ .../global_objects/function/caller/index.html | 69 +++++ .../global_objects/function/displayname/index.html | 121 ++++++++ .../reference/global_objects/function/index.html | 156 ++++++++++ .../global_objects/function/isgenerator/index.html | 40 +++ .../global_objects/function/length/index.html | 89 ++++++ .../global_objects/function/name/index.html | 219 ++++++++++++++ .../global_objects/function/prototype/index.html | 138 +++++++++ .../global_objects/function/tosource/index.html | 49 ++++ .../global_objects/function/tostring/index.html | 230 +++++++++++++++ 14 files changed, 1969 insertions(+) create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/apply/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/arguments/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/arity/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/bind/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/call/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/caller/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/displayname/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/isgenerator/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/length/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/name/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/prototype/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/tosource/index.html create mode 100644 files/zh-cn/web/javascript/reference/global_objects/function/tostring/index.html (limited to 'files/zh-cn/web/javascript/reference/global_objects/function') diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/apply/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/apply/index.html new file mode 100644 index 0000000000..de53da11e7 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/apply/index.html @@ -0,0 +1,219 @@ +--- +title: Function.prototype.apply() +slug: Web/JavaScript/Reference/Global_Objects/Function/apply +tags: + - Function + - JavaScript + - Method +translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply +--- +
{{JSRef}}
+ +

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

+ +
注意:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组
+ +
{{EmbedInteractiveExample("pages/js/function-apply.html")}}
+ + + +

语法

+ +
func.apply(thisArg, [argsArray])
+ +

参数

+ +
+
thisArg
+
必选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于{{jsxref("Strict_mode", "非严格模式", "", 1)}}下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
+
argsArray
+
可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 {{jsxref("null")}} 或  {{jsxref("undefined")}},则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 {{anch("Browser_compatibility", "浏览器兼容性")}} 请参阅本文底部内容。
+
+ +

返回值

+ +

调用有指定this值和参数的函数的结果。

+ +

描述

+ +

在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。

+ +

apply 与 {{jsxref("Function.call", "call()")}} 非常相似,不同之处在于提供参数的方式。apply 使用参数数组而不是一组参数列表。apply 可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas']),或数组对象, 如  fun.apply(this, new Array('eat', 'bananas'))

+ +

你也可以使用 {{jsxref("Functions/arguments", "arguments")}}对象作为 argsArray 参数。 arguments 是一个函数的局部变量。 它可以被用作被调用对象的所有未指定的参数。 这样,你在使用apply函数的时候就不需要知道被调用对象的所有参数。 你可以使用arguments来把所有的参数传递给被调用对象。 被调用对象接下来就负责处理这些参数。

+ +

从 ECMAScript 第5版开始,可以使用任何种类的类数组对象,就是说只要有一个 length 属性和(0..length-1)范围的整数属性。例如现在可以使用 {{domxref("NodeList")}} 或一个自己定义的类似 {'length': 2, '0': 'eat', '1': 'bananas'} 形式的对象。

+ +
+

需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。

+
+ +

示例

+ +

用 apply 将数组各项添加到另一个数组

+ +

我们可以使用push将元素追加到数组中。由于push接受可变数量的参数,所以也可以一次追加多个元素。

+ +

但是,如果push的参数是数组,它会将该数组作为单个元素添加,而不是将这个数组内的每个元素添加进去,因此我们最终会得到一个数组内的数组。如果不想这样呢?concat符合我们的需求,但它并不是将元素添加到现有数组,而是创建并返回一个新数组。 然而我们需要将元素追加到现有数组......那么怎么做好?难道要写一个循环吗?别当然不是!

+ +

apply正派上用场!

+ +
var array = ['a', 'b'];
+var elements = [0, 1, 2];
+array.push.apply(array, elements);
+console.info(array); // ["a", "b", 0, 1, 2]
+
+ +

使用apply和内置函数

+ +

对于一些需要写循环以便历数组各项的需求,我们可以用apply完成以避免循环。

+ +

下面是示例,我们将用Math.max/Math.min求得数组中的最大/小值。

+ +
/* 找出数组中最大/小的数字 */
+var numbers = [5, 6, 2, 3, 7];
+
+/* 使用Math.min/Math.max以及apply 函数时的代码 */
+var max = Math.max.apply(null, numbers); /* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
+var min = Math.min.apply(null, numbers);
+
+/* 对比:简单循环算法 */
+max = -Infinity, min = +Infinity;
+
+for (var i = 0; i < numbers.length; i++) {
+  if (numbers[i] > max)
+    max = numbers[i];
+  if (numbers[i] < min)
+    min = numbers[i];
+}
+ +

注意:如果按上面方式调用apply,有超出JavaScript引擎参数长度上限的风险。一个方法传入过多参数(比如一万个)时的后果在不同JavaScript 引擎中表现不同。(JavaScriptCore引擎中有被硬编码的 参数个数上限:65536)。这是因为此限制(实际上也是任何用到超大栈空间的行为的自然表现)是不明确的。一些引擎会抛出异常,更糟糕的是其他引擎会直接限制传入到方法的参数个数,导致参数丢失。比如:假设某个引擎的方法参数上限为4(实际上限当然要高得多), 这种情况下,上面的代码执行后, 真正被传递到 apply的参数为 5, 6, 2, 3 ,而不是完整的数组。

+ +

如果你的参数数组可能非常大,那么推荐使用下面这种混合策略:将数组切块后循环传入目标方法:

+ +
function minOfArray(arr) {
+  var min = Infinity;
+  var QUANTUM = 32768;
+
+  for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
+    var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
+    min = Math.min(submin, min);
+  }
+
+  return min;
+}
+
+var min = minOfArray([5, 6, 2, 3, 7]);
+
+ +

使用apply来链接构造器

+ +

你可以使用apply来链接一个对象构造器,类似于Java。在接下来的例子中我们会创建一个全局Function 对象的construct方法 ,来使你能够在构造器中使用一个类数组对象而非参数列表。

+ +
Function.prototype.construct = function (aArgs) {
+  var oNew = Object.create(this.prototype);
+  this.apply(oNew, aArgs);
+  return oNew;
+};
+
+ +
+

注意: 上面使用的Object.create()方法相对来说比较新。另一种可选的方法,请考虑如下替代方法:

+ +

Using {{jsxref("Object/__proto__", "Object.__proto__")}}:

+ +
Function.prototype.construct = function (aArgs) {
+  var oNew = {};
+  oNew.__proto__ = this.prototype;
+  this.apply(oNew, aArgs);
+  return oNew;
+};
+ +

使用闭包:

+ +
Function.prototype.construct = function(aArgs) {
+  var fConstructor = this, fNewConstr = function() {
+    fConstructor.apply(this, aArgs);
+  };
+  fNewConstr.prototype = fConstructor.prototype;
+  return new fNewConstr();
+};
+ +

使用 Function 构造器:

+ +
Function.prototype.construct = function (aArgs) {
+  var fNewConstr = new Function("");
+  fNewConstr.prototype = this.prototype;
+  var oNew = new fNewConstr();
+  this.apply(oNew, aArgs);
+  return oNew;
+};
+
+ +

使用示例:

+ +
function MyConstructor (arguments) {
+    for (var nProp = 0; nProp < arguments.length; nProp++) {
+        this["property" + nProp] = arguments[nProp];
+    }
+}
+
+var myArray = [4, "Hello world!", false];
+var myInstance = new MyConstructor(myArray); //Fix MyConstructor.construct is not a function
+
+console.log(myInstance.property1);                // logs "Hello world!"
+console.log(myInstance instanceof MyConstructor); // logs "true"
+console.log(myInstance.constructor);              // logs "MyConstructor"
+
+ +
注意: 这个非native的Function.construct方法无法和一些native构造器(例如Date)一起使用。 在这种情况下你必须使用Function.bind方法(例如,想象有如下一个数组要用在Date构造器中: [2012, 11, 4];这时你需要这样写: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() – -无论如何这不是最好的实现方式并且也许不该用在任何生产环境中).
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES3')}}{{Spec2('ES3')}}Initial definition. Implemented in JavaScript 1.3.
{{SpecName('ES5.1', '#sec-15.3.4.3', 'Function.prototype.apply')}}{{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-function.prototype.apply', 'Function.prototype.apply')}}{{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-function.prototype.apply', 'Function.prototype.apply')}}{{Spec2('ESDraft')}}
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Function.apply")}}

+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/arguments/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/arguments/index.html new file mode 100644 index 0000000000..a0c93f29f3 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/arguments/index.html @@ -0,0 +1,125 @@ +--- +title: Function.arguments +slug: Web/JavaScript/Reference/Global_Objects/Function/arguments +translation_of: Web/JavaScript/Reference/Global_Objects/Function/arguments +--- +
{{JSRef}} {{deprecated_header}}
+ +

function.arguments 属性代表传入函数的实参,它是一个类数组对象。

+ +

描述

+ +

function.arguments 已经被废弃了, 现在推荐的做法是使用函数内部可用的 {{jsxref("Functions/arguments", "arguments")}} 对象来访问函数的实参。

+ +

在函数递归调用的时候(在某一刻同一个函数运行了多次,也就是有多套实参),那么 arguments 属性的值是最近一次该函数调用时传入的实参,下面的示例有演示。

+ +

如果函数不在执行期间,那么该函数的 arguments 属性的值是 null

+ +

示例

+ +
function f(n) { g(n - 1); }
+
+function g(n) {
+  console.log('before: ' + g.arguments[0]);
+  if (n > 0) { f(n); }
+  console.log('after: ' + g.arguments[0]);
+}
+
+f(2);
+
+console.log('函数退出后的 arguments 属性值:' + g.arguments);
+
+// 输出:
+
+// before: 1
+// before: 0
+// after: 0
+// after: 1
+// 函数退出后的 arguments 属性值:null
+
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + +
规范名称规范状态备注
{{SpecName('ES1')}}{{Spec2('ES1')}}arguments 属性首次实现于 JavaScript 1.0,首次添加进规范是在 ES1,在 ES3 中被删除。
{{SpecName('ES5.1', '#sec-10.6', 'arguments object')}}{{Spec2('ES5.1')}}{{jsxref("Functions/arguments", "arguments")}}
{{SpecName('ES6', '#sec-arguments-object', 'arguments object')}}{{Spec2('ES6')}}{{jsxref("Functions/arguments", "arguments")}}
+ +

浏览器兼容性

+ +
{{CompatibilityTable}}
+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
+
+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/arity/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/arity/index.html new file mode 100644 index 0000000000..d8e8668ca2 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/arity/index.html @@ -0,0 +1,16 @@ +--- +title: Function.arity +slug: Web/JavaScript/Reference/Global_Objects/Function/arity +translation_of: Archive/Web/JavaScript/Function.arity +--- +
+
{{JSRef("Global_Objects", "Function")}} {{obsolete_header}}
+
+ +

概述

+ +

返回一个函数的形参数量.

+ +

描述

+ +

arity是一个古老的已经没有浏览器支持的属性,你应该使用Function.prototype.length属性来代替.

diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/bind/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/bind/index.html new file mode 100644 index 0000000000..fbabcdfc13 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/bind/index.html @@ -0,0 +1,324 @@ +--- +title: Function.prototype.bind() +slug: Web/JavaScript/Reference/Global_Objects/Function/bind +tags: + - ECMAScript 2015 + - ECMAScript 5 + - Function + - JavaScript + - Method + - polyfill +translation_of: Web/JavaScript/Reference/Global_Objects/Function/bind +--- +
{{JSRef}}
+ +

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

+ +
{{EmbedInteractiveExample("pages/js/function-bind.html", "taller")}}
+ + + +

语法

+ +
function.bind(thisArg[, arg1[, arg2[, ...]]])
+ +

参数

+ +
+
thisArg
+
调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用{{jsxref("Operators/new", "new")}}运算符构造绑定函数,则忽略该值。当使用 bindsetTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArgnullundefined,执行作用域的 this 将被视为新函数的 thisArg
+
arg1, arg2, ...
+
当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
+
+ +

返回值

+ +

返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。

+ +

描述

+ +
bind() 函数会创建一个新的绑定函数bound function,BF)。绑定函数是一个 exotic function object(怪异函数对象,ECMAScript 2015 中的术语),它包装了原函数对象。调用绑定函数通常会导致执行包装函数
+绑定函数具有以下内部属性:
+ +
+ +
+ + +

当调用绑定函数时,它调用 [[BoundTargetFunction]] 上的内部方法 [[Call]],就像这样 Call(boundThis, args)。其中,boundThis[[BoundThis]]args[[BoundArguments]] 加上通过函数调用传入的参数列表。

+
+ +
+

绑定函数也可以使用 {{jsxref("Operators/new", "new")}} 运算符构造,它会表现为目标函数已经被构建完毕了似的。提供的 this 值会被忽略,但前置参数仍会提供给模拟函数。

+
+ +

示例

+ +

创建绑定函数

+ +

bind() 最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的 this 值。JavaScript新手经常犯的一个错误是将一个方法从对象中拿出来,然后再调用,期望方法中的 this 是原来的对象(比如在回调中传入这个方法)。如果不做特殊处理的话,一般会丢失原来的对象。基于这个函数,用原始的对象创建一个绑定函数,巧妙地解决了这个问题:

+ +
this.x = 9;    // 在浏览器中,this 指向全局的 "window" 对象
+var module = {
+  x: 81,
+  getX: function() { return this.x; }
+};
+
+module.getX(); // 81
+
+var retrieveX = module.getX;
+retrieveX();
+// 返回 9 - 因为函数是在全局作用域中调用的
+
+// 创建一个新函数,把 'this' 绑定到 module 对象
+// 新手可能会将全局变量 x 与 module 的属性 x 混淆
+var boundGetX = retrieveX.bind(module);
+boundGetX(); // 81
+
+ +

偏函数

+ +

bind() 的另一个最简单的用法是使一个函数拥有预设的初始参数。只要将这些参数(如果有的话)作为 bind() 的参数写在 this 后面。当绑定函数被调用时,这些参数会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。

+ +
function list() {
+  return Array.prototype.slice.call(arguments);
+}
+
+function addArguments(arg1, arg2) {
+    return arg1 + arg2
+}
+
+var list1 = list(1, 2, 3); // [1, 2, 3]
+
+var result1 = addArguments(1, 2); // 3
+
+// 创建一个函数,它拥有预设参数列表。
+var leadingThirtysevenList = list.bind(null, 37);
+
+// 创建一个函数,它拥有预设的第一个参数
+var addThirtySeven = addArguments.bind(null, 37);
+
+var list2 = leadingThirtysevenList();
+// [37]
+
+var list3 = leadingThirtysevenList(1, 2, 3);
+// [37, 1, 2, 3]
+
+var result2 = addThirtySeven(5);
+// 37 + 5 = 42
+
+var result3 = addThirtySeven(5, 10);
+// 37 + 5 = 42 ,第二个参数被忽略
+
+ +

配合 setTimeout

+ +

在默认情况下,使用 {{ domxref("window.setTimeout()") }} 时,this 关键字会指向 {{ domxref("window") }} (或 global)对象。当类的方法中需要 this 指向类的实例时,你可能需要显式地把 this 绑定到回调函数,就不会丢失该实例的引用。

+ +
function LateBloomer() {
+  this.petalCount = Math.ceil(Math.random() * 12) + 1;
+}
+
+// 在 1 秒钟后声明 bloom
+LateBloomer.prototype.bloom = function() {
+  window.setTimeout(this.declare.bind(this), 1000);
+};
+
+LateBloomer.prototype.declare = function() {
+  console.log('I am a beautiful flower with ' +
+    this.petalCount + ' petals!');
+};
+
+var flower = new LateBloomer();
+flower.bloom();  // 一秒钟后, 调用 'declare' 方法
+ +

作为构造函数使用的绑定函数

+ +
+

警告 :这部分演示了 JavaScript 的能力并且记录了 bind() 的超前用法。以下展示的方法并不是最佳的解决方案,且可能不应该用在任何生产环境中。

+
+ +

绑定函数自动适应于使用 {{jsxref("Operators/new", "new")}} 操作符去构造一个由目标函数创建的新实例。当一个绑定函数是用来构建一个值的,原来提供的 this 就会被忽略。不过提供的参数列表仍然会插入到构造函数调用时的参数列表之前。

+ +
function Point(x, y) {
+  this.x = x;
+  this.y = y;
+}
+
+Point.prototype.toString = function() {
+  return this.x + ',' + this.y;
+};
+
+var p = new Point(1, 2);
+p.toString(); // '1,2'
+
+var emptyObj = {};
+var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
+
+// 本页下方的 polyfill 不支持运行这行代码,
+// 但使用原生的 bind 方法运行是没问题的:
+
+var YAxisPoint = Point.bind(null, 0/*x*/);
+
+/*(译注:polyfill 的 bind 方法中,如果把 bind 的第一个参数加上,
+即对新绑定的 this 执行 Object(this),包装为对象,
+因为 Object(null) 是 {},所以也可以支持)*/
+
+var axisPoint = new YAxisPoint(5);
+axisPoint.toString(); // '0,5'
+
+axisPoint instanceof Point; // true
+axisPoint instanceof YAxisPoint; // true
+new YAxisPoint(17, 42) instanceof Point; // true
+ +

请注意,你不需要做特别的处理就可以用 {{jsxref("Operators/new", "new")}} 操作符创建一个绑定函数。也就是说,你不需要做特别处理就可以创建一个可以被直接调用的绑定函数,即使你更希望绑定函数是用 {{jsxref("Operators/new", "new")}} 操作符来调用。

+ +
// ...接着上面的代码继续的话,
+// 这个例子可以直接在你的 JavaScript 控制台运行
+
+// 仍然能作为一个普通函数来调用
+// (即使通常来说这个不是被期望发生的)
+YAxisPoint(13);
+
+emptyObj.x + ',' + emptyObj.y;   //  '0,13'
+
+ +

如果你希望一个绑定函数要么只能用 {{jsxref("Operators/new", "new")}} 操作符,要么只能直接调用,那你必须在目标函数上显式规定这个限制。

+ +

快捷调用

+ +

在你想要为一个需要特定的 this 值的函数创建一个捷径(shortcut)的时候,bind() 也很好用。

+ +

你可以用 {{jsxref("Array.prototype.slice")}} 来将一个类似于数组的对象(array-like object)转换成一个真正的数组,就拿它来举例子吧。你可以简单地这样写:

+ +
var slice = Array.prototype.slice;
+
+// ...
+
+slice.apply(arguments);
+ +

bind()可以使这个过程变得简单。在下面这段代码里面,slice 是 {{jsxref("Function.prototype")}} 的 {{jsxref("Function.prototype.apply()", "apply()")}} 方法的绑定函数,并且将 {{jsxref("Array.prototype")}} 的 {{jsxref("Array.prototype.slice()", "slice()")}} 方法作为 this 的值。这意味着我们压根儿用不着上面那个 apply()调用了。

+ +
// 与前一段代码的 "slice" 效果相同
+var unboundSlice = Array.prototype.slice;
+var slice = Function.prototype.apply.bind(unboundSlice);
+
+// ...
+
+slice(arguments);
+ +

Polyfill

+ +

有两种实现bind的方法,下面第一种不支持使用new调用新创建的构造函数,而第二种支持。

+ +
// Does not work with `new (funcA.bind(thisArg, args))`
+if (!Function.prototype.bind) (function(){
+  var slice = Array.prototype.slice;
+  Function.prototype.bind = function() {
+    var thatFunc = this, thatArg = arguments[0];
+    var args = slice.call(arguments, 1);
+    if (typeof thatFunc !== 'function') {
+      // closest thing possible to the ECMAScript 5
+      // internal IsCallable function
+      throw new TypeError('Function.prototype.bind - ' +
+             'what is trying to be bound is not callable');
+    }
+    return function(){
+      var funcArgs = args.concat(slice.call(arguments))
+      return thatFunc.apply(thatArg, funcArgs);
+    };
+  };
+})();
+ +

你可以将这段代码插入到你的脚本开头,从而使你的 bind() 在没有内置实现支持的环境中也可以部分地使用bind

+ +
//  Yes, it does work with `new (funcA.bind(thisArg, args))`
+if (!Function.prototype.bind) (function(){
+  var ArrayPrototypeSlice = Array.prototype.slice;
+  Function.prototype.bind = function(otherThis) {
+    if (typeof this !== 'function') {
+      // closest thing possible to the ECMAScript 5
+      // internal IsCallable function
+      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+    }
+
+    var baseArgs= ArrayPrototypeSlice.call(arguments, 1),
+        baseArgsLength = baseArgs.length,
+        fToBind = this,
+        fNOP    = function() {},
+        fBound  = function() {
+          baseArgs.length = baseArgsLength; // reset to default base arguments
+          baseArgs.push.apply(baseArgs, arguments);
+          return fToBind.apply(
+                 fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
+          );
+        };
+
+    if (this.prototype) {
+      // Function.prototype doesn't have a prototype property
+      fNOP.prototype = this.prototype;
+    }
+    fBound.prototype = new fNOP();
+
+    return fBound;
+  };
+})();
+ +

上述算法和实际的实现算法还有许多其他的不同 (尽管可能还有其他不同之处,但已经没有必要再多列举):

+ + + +

如果你选择使用这部分实现,你不能依赖于那些与 ECMA-262, 5th edition 规定的行为偏离的例子。bind() 函数被广泛支持之前,某些情况下(或者为了兼容某些特定需求对其做一些特定修改后)可以选择用这个实现作为过渡。

+ +

请访问 https://github.com/Raynos/function-bind 以查找更完整的解决方案!

+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + +
规范状态备注
{{SpecName('ES5.1', '#sec-15.3.4.5', 'Function.prototype.bind')}}{{Spec2('ES5.1')}}初始定义。在 JavaScript 1.8.5 中实现。
{{SpecName('ES2015', '#sec-function.prototype.bind', 'Function.prototype.bind')}}{{Spec2('ES2015')}}
{{SpecName('ESDraft', '#sec-function.prototype.bind', 'Function.prototype.bind')}}{{Spec2('ESDraft')}}
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Function.bind")}}

+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/call/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/call/index.html new file mode 100644 index 0000000000..5b9fc87b48 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/call/index.html @@ -0,0 +1,174 @@ +--- +title: Function.prototype.call() +slug: Web/JavaScript/Reference/Global_Objects/Function/call +tags: + - JavaScript + - 函数 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Function/call +--- +
{{JSRef}}
+ +

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

+ +
注意:该方法的语法和作用与 {{jsxref("Function.apply", "apply()")}} 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组
+ +
{{EmbedInteractiveExample("pages/js/function-call.html")}}
+ + + +

语法

+ +
function.call(thisArg, arg1, arg2, ...)
+ +

参数

+ +
+
thisArg
+
可选的。在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
+
arg1, arg2, ...
+
指定的参数列表。
+
+ +

返回值

+ +

使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined

+ +

描述

+ +

call() 允许为不同的对象分配和调用属于一个对象的函数/方法。

+ +

call() 提供新的 this 值给当前调用的函数/方法。你可以使用 call 来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。

+ +

示例

+ +

使用 call 方法调用父构造函数

+ +

在一个子构造函数中,你可以通过调用父构造函数的 call 方法来实现继承,类似于 Java 中的写法。下例中,使用 FoodToy 构造函数创建的对象实例都会拥有在 Product 构造函数中添加的 name 属性和 price 属性,但 category 属性是在各自的构造函数中定义的。

+ +
function Product(name, price) {
+  this.name = name;
+  this.price = price;
+}
+
+function Food(name, price) {
+  Product.call(this, name, price);
+  this.category = 'food';
+}
+
+function Toy(name, price) {
+  Product.call(this, name, price);
+  this.category = 'toy';
+}
+
+var cheese = new Food('feta', 5);
+var fun = new Toy('robot', 40);
+
+ +

使用 call 方法调用匿名函数

+ +

在下例中的 for 循环体内,我们创建了一个匿名函数,然后通过调用该函数的 call 方法,将每个数组元素作为指定的 this 值执行了那个匿名函数。这个匿名函数的主要目的是给每个数组元素对象添加一个 print 方法,这个 print 方法可以打印出各元素在数组中的正确索引号。当然,这里不是必须得让数组元素作为 this 值传入那个匿名函数(普通参数就可以),目的是为了演示 call 的用法。

+ +
var animals = [
+  { species: 'Lion', name: 'King' },
+  { species: 'Whale', name: 'Fail' }
+];
+
+for (var i = 0; i < animals.length; i++) {
+  (function(i) {
+    this.print = function() {
+      console.log('#' + i + ' ' + this.species
+                  + ': ' + this.name);
+    }
+    this.print();
+  }).call(animals[i], i);
+}
+
+ +

使用 call 方法调用函数并且指定上下文的 'this'

+ +

在下面的例子中,当调用 greet 方法的时候,该方法的this值会绑定到 obj 对象。

+ +
function greet() {
+  var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
+  console.log(reply);
+}
+
+var obj = {
+  animal: 'cats', sleepDuration: '12 and 16 hours'
+};
+
+greet.call(obj);  // cats typically sleep between 12 and 16 hours
+
+ +

使用 call 方法调用函数并且不指定第一个参数(argument

+ +

在下面的例子中,我们调用了 display 方法,但并没有传递它的第一个参数。如果没有传递第一个参数,this 的值将会被绑定为全局对象。

+ +
var sData = 'Wisen';
+
+function display() {
+  console.log('sData value is %s ', this.sData);
+}
+
+display.call();  // sData value is Wisen
+ +
+

注意:在严格模式下,this 的值将会是 undefined。见下文。

+
+ +
'use strict';
+
+var sData = 'Wisen';
+
+function display() {
+  console.log('sData value is %s ', this.sData);
+}
+
+display.call(); // Cannot read the property of 'sData' of undefined
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
规范版本状态说明
{{SpecName('ES1')}}{{Spec2('ES1')}}初始定义。在 JavaScript 1.3 中实现。
{{SpecName('ES5.1', '#sec-15.3.4.4', 'Function.prototype.call')}}{{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-function.prototype.call', 'Function.prototype.call')}}{{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-function.prototype.call', 'Function.prototype.call')}}{{Spec2('ESDraft')}}
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Function.call")}}

+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/caller/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/caller/index.html new file mode 100644 index 0000000000..a850d41582 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/caller/index.html @@ -0,0 +1,69 @@ +--- +title: Function.caller +slug: Web/JavaScript/Reference/Global_Objects/Function/caller +translation_of: Web/JavaScript/Reference/Global_Objects/Function/caller +--- +
{{JSRef("Global_Objects", "Function")}} {{non-standard_header}}
+ +

概述

+ +

返回调用指定函数的函数.

+ +

该属性不是ECMA-262第3版标准的一部分.不过, SpiderMonkey (Mozilla的JavaScript引擎) (查看{{ Bug("65683") }}), V8 (Chrome的JavaScript引擎) 和 JScript(IE的ECMAScript实现)都已经支持了它.

+ +

描述

+ +

如果一个函数f是在全局作用域内被调用的,则f.caller为null,相反,如果一个函数是在另外一个函数作用域内被调用的,则f.caller指向调用它的那个函数.

+ +

该属性的常用形式arguments.callee.caller替代了被废弃的 arguments.caller.

+ +

备注

+ +

注意,在使用递归调用时, 你不能使用此属性来重现出调用栈.请考虑以下代码:

+ +
function f(n) { g(n-1) }
+function g(n) { if(n>0) f(n); else stop() }
+f(2)
+
+ +

stop()函数被调用时,调用栈是这样的:

+ +
f(2) -> g(1) -> f(1) -> g(0) -> stop()
+
+ +

由于下面的表达式为 true(只保留函数最后一次被调用时的caller):

+ +
stop.caller === g && f.caller === g && g.caller === f
+
+ +

所以如果你尝试在stop()函数中获取调用栈的话:

+ +
var f = stop;
+var stack = "调用栈:";
+while (f) {
+  stack += "\n" + f.name;
+  f = f.caller;
+}
+
+ +

则上面的代码会进入一个死循环.

+ +

有一个特殊属性 __caller__, 可以返回调用当前函数的函数的活动对象(可以用来重现出整个调用栈), 但由于安全原因的考虑,该属性已被删除.

+ +

例子

+ +

例子: 检测一个函数的caller属性的值

+ +

下例用来得出一个函数是被谁调用的.

+ +
function myFunc() {
+   if (myFunc.caller == null) {
+      return ("该函数在全局作用域内被调用!");
+   } else
+      return ("调用我的是函数是" + myFunc.caller);
+}
+
+ +

浏览器兼容性

+ +

Function.caller目前被所有主流浏览器支持: Firefox, Safari, Chrome, Opera 和 IE. 查看检测结果.

diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/displayname/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/displayname/index.html new file mode 100644 index 0000000000..abf8452f93 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/displayname/index.html @@ -0,0 +1,121 @@ +--- +title: Function.displayName +slug: Web/JavaScript/Reference/Global_Objects/Function/displayName +translation_of: Web/JavaScript/Reference/Global_Objects/Function/displayName +--- +
{{JSRef}} {{non-standard_header}}
+ +

function.displayName 属性获取函数的显示名称

+ +

Description 描述

+ +

当一个函数的 displayName 属性被定义,这个函数的 displayName 属性将返回显示名称。

+ +
function doSomething() {}
+
+console.log(doSomething.displayName); // "undefined"
+
+var popup = function(content) { console.log(content); };
+
+popup.displayName = 'Show Popup';
+
+console.log(popup.displayName); // "Show Popup"
+
+ +

可以在函数表达式重定义函数的显示名称{{jsxref("Functions", "function expression", "", 1)}}:

+ +
var object = {
+  someMethod: function() {}
+};
+
+object.someMethod.displayName = 'someMethod';
+
+console.log(object.someMethod.displayName); // logs "someMethod"
+
+try { someMethod } catch(e) { console.log(e); }
+// ReferenceError: someMethod is not defined
+
+ +

可以动态修改函数的显示名称:

+ +
var object = {
+  // anonymous
+  someMethod: function(value) {
+    arguments.callee.displayName = 'someMethod (' + value + ')';
+  }
+};
+
+console.log(object.someMethod.displayName); // "undefined"
+
+object.someMethod('123')
+console.log(object.someMethod.displayName); // "someMethod (123)"
+
+ +

Examples 例子

+ +

这个显示名称通常在控制台和配置文件中,用它来提醒对它背后的真实函数名 {{jsxref("Function.name", "func.name")}}的引用。例如:

+ +

通过如下的举例,显示的名称应该显示像"function My Function()"

+ +
var a = function() {};
+a.displayName = 'My Function';
+
+a; // "function My Function()"
+ +

Specifications 规范

+ +

不属于任何规范

+ +

Browser compatibility 浏览器兼容性

+ +

如果你愿意贡献数据,请访问https://github.com/mdn/browser-compat-data并同时给我们发送推送请求。

+ +
{{CompatibilityTable}}
+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support{{CompatUnknown}}{{CompatGeckoDesktop(13)}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}
+
diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/index.html new file mode 100644 index 0000000000..217ac78e3d --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/index.html @@ -0,0 +1,156 @@ +--- +title: Function +slug: Web/JavaScript/Reference/Global_Objects/Function +tags: + - Constructor + - Function + - JavaScript + - 函数 + - 构造器 +translation_of: Web/JavaScript/Reference/Global_Objects/Function +--- +
{{JSRef}}
+ +
每个 JavaScript 函数实际上都是一个 Function 对象。运行 (function(){}).constructor === Function // true 便可以得到这个结论。
+ +

构造函数

+ +

Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遇到和 {{jsxref("eval")}} 类似的的安全问题和(相对较小的)性能问题。然而,与 eval 不同的是,Function 创建的函数只能在全局作用域中运行。

+ +
{{EmbedInteractiveExample("pages/js/function-constructor.html")}}
+ + + +

语法

+ +
new Function ([arg1[, arg2[, ...argN]],] functionBody)
+ +

参数

+ +
+
arg1, arg2, ... argN
+
被函数使用的参数的名称必须是合法命名的。参数名称是一个有效的JavaScript标识符的字符串,或者一个用逗号分隔的有效字符串的列表;例如“×”,“theValue”,或“a,b”。
+
functionBody
+
一个含有包括函数定义的 JavaScript 语句的字符串
+
+ +

描述

+ +

使用 Function 构造器生成的 Function 对象是在函数创建时解析的。这比你使用函数声明或者函数表达式并在你的代码中调用更为低效,因为使用后者创建的函数是跟其他代码一起解析的。

+ +

所有被传递到构造函数中的参数,都将被视为将被创建的函数的参数,并且是相同的标示符名称和传递顺序。

+ +

以调用函数的方式调用 Function 的构造函数(而不是使用 new 关键字) 跟以构造函数来调用是一样的。

+ +

属性和方法

+ +

全局的 Function 对象没有自己的属性和方法,但是,因为它本身也是一个函数,所以它也会通过原型链从自己的原型链 {{jsxref("Function.prototype")}} 上继承一些属性和方法。

+ +

原型对象

+ +

属性

+ +
{{page('/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype', '属性')}}
+ +

方法

+ +
{{page('/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype', '方法')}}
+ +

实例

+ +

Function 实例从 {{jsxref("Function.prototype")}} 继承了一些属性和方法。 同其他构造函数一样, 你可以改变构造函数的原型从而使得所有的 Function 实例的属性和方法发生改变。

+ +

示例

+ +

传入参数调用 Function 构造函数

+ +

下面的代码会创建一个需要两个参数的 Function 对象。

+ +
// 可以直接在 JavaScript 控制台中运行
+
+// 创建了一个能返回两个参数和的函数
+const adder = new Function("a", "b", "return a + b");
+
+// 调用函数
+adder(2, 6);
+// > 8
+
+ +

参数 "a" 和 "b" 是参数的名字,在函数体中被使用,"return a + b"。

+ +

Function 构造器与函数声明之间的不同

+ +

由 Function 构造器创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境,因此在运行时它们只能访问全局变量和自己的局部变量,不能访问它们被 Function 构造器创建时所在的作用域的变量。这一点与使用 {{jsxref("eval")}} 执行创建函数的代码不同。

+ +
var x = 10;
+
+function createFunction1() {
+    var x = 20;
+    return new Function('return x;'); // 这里的 x 指向最上面全局作用域内的 x
+}
+
+function createFunction2() {
+    var x = 20;
+    function f() {
+        return x; // 这里的 x 指向上方本地作用域内的 x
+    }
+    return f;
+}
+
+var f1 = createFunction1();
+console.log(f1());          // 10
+var f2 = createFunction2();
+console.log(f2());          // 20
+
+ +

虽然这段代码可以在浏览器中正常运行,但在 Node.js 中 f1() 会产生一个“找不到变量 x ”的 ReferenceError。这是因为在 Node 中顶级作用域不是全局作用域,而 x 其实是在当前模块的作用域之中。

+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES1')}}{{Spec2('ES1')}}Initial definition. Implemented in JavaScript 1.0.
{{SpecName('ES5.1', '#sec-15.3', 'Function')}}{{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-function-objects', 'Function')}}{{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-function-objects', 'Function')}}{{Spec2('ESDraft')}}
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Function")}}

+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/isgenerator/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/isgenerator/index.html new file mode 100644 index 0000000000..f377f0a210 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/isgenerator/index.html @@ -0,0 +1,40 @@ +--- +title: Function.prototype.isGenerator() +slug: Web/JavaScript/Reference/Global_Objects/Function/isGenerator +translation_of: Archive/Web/JavaScript/Function.isGenerator +--- +
{{JSRef("Global_Objects", "Function")}} {{non-standard_header}}
+ +

概述

+ +

判断一个函数是否是一个生成器.

+ +

语法

+ +
fun.isGenerator()
+ +

描述

+ +

该方法用来判断一个函数是否是一个生成器.

+ +

例子

+ +
function f() {}
+function* g() {
+  yield 42;
+}
+console.log("f.isGenerator() = " + f.isGenerator());
+console.log("g.isGenerator() = " + g.isGenerator());
+
+ +

上面代码的输出结果为

+ +
f.isGenerator() = false
+g.isGenerator() = true
+
+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/length/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/length/index.html new file mode 100644 index 0000000000..9804d07a75 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/length/index.html @@ -0,0 +1,89 @@ +--- +title: Function.length +slug: Web/JavaScript/Reference/Global_Objects/Function/length +tags: + - Function + - JavaScript + - Property +translation_of: Web/JavaScript/Reference/Global_Objects/Function/length +--- +
{{JSRef}}
+ +

length 属性指明函数的形参个数。

+ +

{{EmbedInteractiveExample("pages/js/function-length.html")}}

+ +
{{js_property_attributes(0,0,1)}}
+ +

描述

+ +

length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。

+ +

形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数。

+ +

与之对比的是,  {{jsxref("Functions_and_function_scope/arguments/length", "arguments.length")}} 是函数被调用时实际传参的个数。

+ +

Function 构造器的属性

+ +

{{jsxref("Function")}} 构造器本身也是个Function。他的 length 属性值为 1 。该属性 Writable: false, Enumerable: false, Configurable: true.

+ +

Function.prototype 对象的属性

+ +

 {{jsxref("Function.prototype")}}  对象的 length 属性值为 0 。

+ +

示例

+ +
console.log(Function.length); /* 1 */
+
+console.log((function()        {}).length); /* 0 */
+console.log((function(a)       {}).length); /* 1 */
+console.log((function(a, b)    {}).length); /* 2 etc. */
+
+console.log((function(...args) {}).length);
+// 0, rest parameter is not counted
+
+console.log((function(a, b = 1, c) {}).length);
+// 1, only parameters before the first one with
+// a default value is counted
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES1')}}{{Spec2('ES1')}}Initial definition. Implemented in JavaScript 1.1.
{{SpecName('ES5.1', '#sec-15.3.5.1', 'Function.length')}}{{Spec2('ES5.1')}} 
{{SpecName('ES6', '#sec-function-instances-length', 'Function.length')}}{{Spec2('ES6')}}The configurable attribute of this property is now true.
{{SpecName('ESDraft', '#sec-function-instances-length', 'Function.length')}}{{Spec2('ESDraft')}} 
+ +

浏览器兼容

+ +
{{Compat("javascript.builtins.Function.length")}}
+ +

参见

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/name/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/name/index.html new file mode 100644 index 0000000000..3c701acdca --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/name/index.html @@ -0,0 +1,219 @@ +--- +title: Function.name +slug: Web/JavaScript/Reference/Global_Objects/Function/name +tags: + - ECMAScript 2015 + - Function + - JavaScript + - Property +translation_of: Web/JavaScript/Reference/Global_Objects/Function/name +--- +
{{JSRef("Global_Objects", "Function")}}
+ +
function.name 属性返回函数实例的名称。
+ +

{{js_property_attributes(0,0,1)}}

+ +
+

请注意,在非标准的ES2015之前的实现中,configurable属性也是false 。

+
+ +

示例

+ +

函数声明的名称

+ +

 name 属性返回一个函数声明的名称。

+ +
function doSomething() { }
+doSomething.name;  // "doSomething"
+
+ +

构造函数的名称

+ +

使用new Function(...)语法创建的函数或只是 Function(...) create {{jsxref("Function")}}对象及其名称为“anonymous”。

+ +
(new Function).name; // "anonymous"
+ +

推断函数名称

+ +

变量和方法可以从句法位置推断匿名函数的名称(ECMAScript 2015中新增)。

+ +
var f = function() {};
+var object = {
+  someMethod: function() {}
+};
+
+console.log(f.name); // "f"
+console.log(object.someMethod.name); // "someMethod"
+ +

你可以在 {{jsxref("Operators/Function", "函数表达式", "", 1)}}中定义函数的名称:

+ +
var object = {
+  someMethod: function object_someMethod() {}
+};
+
+console.log(object.someMethod.name); // "object_someMethod"
+
+try { object_someMethod } catch(e) { alert(e); }
+// ReferenceError: object_someMethod is not defined
+
+ +

你不能更改函数的名称,此属性是只读的:

+ + + +
var object = {
+  // anonymous
+  someMethod: function() {}
+};
+
+object.someMethod.name = 'otherMethod';
+console.log(object.someMethod.name); // someMethod
+ +

要更改它,可以使用{{jsxref("Object.defineProperty()")}}。

+ +

简写方法的名称

+ +
var o = {
+  foo(){}
+};
+o.foo.name; // "foo";
+ +

绑定函数的名称

+ +

{{jsxref("Function.bind()")}} 所创建的函数将会在函数的名称前加上"bound " 。

+ +
function foo() {};
+foo.bind({}).name; // "bound foo"
+ +

getters 和 setters 的函数名

+ +

当通过 get 和 set 访问器来存取属性时, "get" 或 "set" 会出现在函数名称前。

+ +
var o = {
+  get foo(){},
+  set foo(x){}
+};
+
+var descriptor = Object.getOwnPropertyDescriptor(o, "foo");
+descriptor.get.name; // "get foo"
+descriptor.set.name; // "set foo";
+ +

类中的函数名称

+ +

你可以使用obj.constructor.name来检查对象的“类”(但请务必阅读以下警告):

+ +
function Foo() {}  // ES2015 Syntax: class Foo {}
+
+var fooInstance = new Foo();
+console.log(fooInstance.constructor.name); // logs "Foo"
+ +
+

警告:脚本解释器只有在函数没有名为name的属性时才会设置内置的Function.name属性(参见 9.2.11 of the ECMAScript2015 Language Specification)。但是,ES2015规定由关键字static修饰的静态方法也会被认为是类的属性(ECMAScript2015, 14.5.14.21.b + 12.2.6.9)。

+
+ +

因此,我们无法获取具有静态方法属性name()的几乎任何类的类名称:

+ +
class Foo {
+  constructor() {}
+  static name() {}
+}
+
+ +

使用static name()方法Foo.name不再保存实际的类名称,而是引用name()函数对象。 ES2015语法中的上述类定义将在Chrome或Firefox中运行,类似于ES5语法中的以下代码段:

+ +
function Foo() {}
+Object.defineProperty(Foo, 'name', { writable: true });
+Foo.name = function() {};
+
+ +

通过fooInstance.constructor.name获取fooInstance类不会给我们所有的类名,而是静态类方法的引用。 例如:

+ +
var fooInstance = new Foo();
+console.log(fooInstance.constructor.name); // logs function name()
+ +

你也可以从ES5语法示例中看到,在Chrome或Firefox的中静态定义的Foo.name变得可写。内置定义在没有自定义静态定义时是只读的:

+ +
Foo.name = 'Hello';
+console.log(Foo.name);
+//如果Foo具有静态name()属性,则输出“Hello”,否则为“Foo”
+
+ +

因此,你不能依赖内置的Function.name属性来保持一个类的名称。

+ +

Symbol作为函数名称

+ +

如果{{jsxref("Symbol")}} 被用于函数名称,并且这个symbol具有相应的描述符,那么方法的名字就是方括号中的描述符。

+ +
var sym1 = Symbol("foo");
+var sym2 = Symbol();
+var o = {
+  [sym1]: function(){},
+  [sym2]: function(){}
+};
+
+o[sym1].name; // "[foo]"
+o[sym2].name; // ""
+
+ +

JavaScript 压缩和 minifiers

+ +
+

警告:当使用Function.name和那些JavaScript压缩器(minifiers)或混淆器进行源码转换时要小心。这些工具通常用作JavaScript构建管道的一部分,以在程序部署到生产之前减少程序的大小。但这种转换通常会在构建时更改函数的名称。

+
+ +

例如下面的代码:

+ +
function Foo() {};
+var foo = new Foo();
+
+if (foo.constructor.name === 'Foo') {
+  console.log("'foo' is an instance of 'Foo'");
+} else {
+  console.log('Oops!');
+}
+ +

可能被压缩为:

+ +
function a() {};
+var b = new a();
+if (b.constructor.name === 'Foo') {
+  console.log("'foo' is an instance of 'Foo'");
+} else {
+  console.log('Oops!');
+}
+
+ +

在未压缩版本中,程序运行到真实分支并打印'foo' is an instance of 'Foo'。 而在压缩版本中,它的行为不同,并且进入else分支。如果您依赖于Function.name,就像上面的示例一样,确保您的构建管道不会更改函数名称,也不要假定函数具有特定的名称。

+ +
+

规范

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES2015', '#sec-name', 'name')}}{{Spec2('ES2015')}}Initial definition.
{{SpecName('ESDraft', '#sec-name', 'name')}}{{Spec2('ESDraft')}} 
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Function.name")}}

+
diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/prototype/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/prototype/index.html new file mode 100644 index 0000000000..afae311604 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/prototype/index.html @@ -0,0 +1,138 @@ +--- +title: Function.prototype +slug: Web/JavaScript/Reference/Global_Objects/Function/prototype +tags: + - JavaScript + - 函数 + - 原型 + - 原型属性 +translation_of: Web/JavaScript/Reference/Global_Objects/Function +--- +
{{JSRef}}
+ +

Function.prototype 属性存储了 {{jsxref("Function")}} 的原型对象。

+ +

描述

+ +

{{jsxref("Function")}}对象继承自 Function.prototype 属性。因此,Function.prototype 不能被修改。

+ +

属性

+ +
+
{{jsxref("Function.arguments")}} {{deprecated_inline()}}
+
以数组形式获取传入函数的所有参数。此属性已被{{jsxref("Functions_and_function_scope/arguments", "arguments")}}替代。
+
{{jsxref("Function.arity")}} {{obsolete_inline() }}
+
用于指定的函数的参数的个数,但已被删除。使用{{jsxref("Function.length","length")}}属性代替。
+
{{jsxref("Function.caller")}} {{ Non-standard_inline() }}
+
获取调用函数的具体对象。
+
{{jsxref("Function.length")}}
+
获取函数的接收参数个数。
+
{{jsxref("Function.name")}} {{ Non-standard_inline() }}
+
获取函数的名称。
+
{{jsxref("Function.displayName")}} {{ Non-standard_inline() }}
+
获取函数的display name。
+
Function.prototype.constructor
+
声明函数的原型构造方法,详细请参考 {{jsxref("Object.constructor")}} 。
+
+ +

方法

+ +
+
{{jsxref("Function.prototype.apply()")}}
+
在一个对象的上下文中应用另一个对象的方法;参数能够以数组形式传入。
+
{{jsxref("Function.prototype.bind()")}}
+
bind()方法会创建一个新函数,称为绑定函数.当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind()方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.
+
{{jsxref("Function.prototype.call()")}}
+
在一个对象的上下文中应用另一个对象的方法;参数能够以列表形式传入。
+
{{jsxref("Function.prototype.isGenerator()")}} {{ Non-standard_inline() }}
+
若函数对象为generator,返回true,反之返回 false
+
{{jsxref("Function.prototype.toSource()")}} {{ Non-standard_inline() }}
+
获取函数的实现源码的字符串。 覆盖了 {{jsxref("Object.prototype.toSource")}} 方法。
+
{{jsxref("Function.prototype.toString()")}}
+
获取函数的实现源码的字符串。覆盖了 {{jsxref("Object.prototype.toString")}} 方法。
+
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + +
规范状态说明
{{SpecName('ES1')}}{{Spec2('ES1')}}Initial definition.Implemented in JavaScript 1.1
{{SpecName('ES5.1', '#sec-15.3.5.2', 'Function.prototype')}}{{Spec2('ES5.1')}} 
{{SpecName('ES6', '#sec-function-instances-prototype', 'Function.prototype')}}{{Spec2('ES6')}} 
+ +

浏览器兼容性

+ +

{{ CompatibilityTable() }}

+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}{{ CompatVersionUnknown() }}
+
+ +

参考

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/tosource/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/tosource/index.html new file mode 100644 index 0000000000..5c4de38138 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/tosource/index.html @@ -0,0 +1,49 @@ +--- +title: Function.prototype.toSource() +slug: Web/JavaScript/Reference/Global_Objects/Function/toSource +translation_of: Web/JavaScript/Reference/Global_Objects/Function/toSource +--- +
+
{{JSRef("Global_Objects", "Function")}} {{non-standard_header}}
+
+ +

概述

+ +

返回函数的源代码的字符串表示.

+ +

语法

+ +
function.toSource();
+Function.toSource();
+
+ +

参数

+ +

+ +

描述

+ +

toSource方法返回下面的值:

+ +

+ + + +
function Function() {
+    [native code]
+}
+ + + +

该方法通常在引擎内部调用.你可以在调试的时候用该方法开查看一个函数的源代码.

+ +

相关链接

+ + diff --git a/files/zh-cn/web/javascript/reference/global_objects/function/tostring/index.html b/files/zh-cn/web/javascript/reference/global_objects/function/tostring/index.html new file mode 100644 index 0000000000..01bf4d2ce7 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/function/tostring/index.html @@ -0,0 +1,230 @@ +--- +title: Function.prototype.toString() +slug: Web/JavaScript/Reference/Global_Objects/Function/toString +tags: + - Function + - JavaScript + - Method +translation_of: Web/JavaScript/Reference/Global_Objects/Function/toString +--- +
{{JSRef}}
+ +

toString() 方法返回一个表示当前函数源代码的字符串。

+ +
{{EmbedInteractiveExample("pages/js/function-tostring.html")}}
+ +

语法

+ +
function.toString()
+ +

返回值

+ +

表示函数源代码的一个字符串

+ +

描述

+ +

{{jsxref("Function")}}对象覆盖了从{{jsxref("Object")}}继承来的{{jsxref("Object.prototype.toString", "toString")}} 方法。对于用户定义的 {{jsxref("Function")}} 对象,toString方法返回一个字符串,其中包含用于定义函数的源文本段。

+ +

在{{jsxref("Function")}}需要转换为字符串时,通常会自动调用函数的 toString 方法。

+ +

this 不是 Function 对象,则 toString() 方法将抛出 {{jsxref("TypeError")}}  ("Function.prototype.toString called on incompatible object") 异常,比如 {{jsxref("Proxy")}} 对象就会抛出异常。

+ +
Function.prototype.toString.call('foo'); // TypeError
+
+ +

如果是在内置函数或由 Function.prototype.bind 返回的函数上调用 toString(),则toString() 返回原生代码字符串,如下

+ +
"function () {\n    [native code]\n}"
+
+ +

若是在由 Function 构造器生成的函数上调用 toString() ,则 toString() 返回创建后的函数源码,包括形参和函数体,函数名为 "anonymous"。

+ +

示例

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionFunction.prototype.toString result
+
+function f(){}
+
+
+"function f(){}"
+
+
+class A { a(){} }
+
+
+"class A { a(){} }"
+
+
+function* g(){}
+
+
+"function* g(){}"
+
+
+a => a
+
+
+"a => a"
+
+
+({ a(){} }.a)
+
+
+"a(){}"
+
+
+({ *a(){} }.a)
+
+
+"*a(){}"
+
+
+({ [0](){} }[0])
+
+
+"[0](){}"
+
+
+Object.getOwnPropertyDescriptor({
+    get a(){}
+}, "a").get
+
+
+"get a(){}"
+
+
+Object.getOwnPropertyDescriptor({
+    set a(x){}
+}, "a").set
+
+
+"set a(x){}"
+
+
+Function.prototype.toString
+
+
+"function toString() { [native code] }"
+
+
+(function f(){}.bind(0))
+
+
+"function () { [native code] }"
+
+
+Function("a", "b")
+
+
+"function anonymous(a\n) {\nb\n}"
+
+ +

规范

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
规范版本规范状态注解
{{SpecName('ES1')}}{{Spec2('ES1')}}初始定义。在 JavaScript 1.1 中实现。
{{SpecName('ES6', '#sec-function.prototype.tostring', 'Function.prototype.toString')}}{{Spec2('ES6')}}对字符串表示增加了更多的特定需求。
Function.prototype.toString revisionDraft对内置函数与行尾表示进行标准化。
{{SpecName('ESDraft', '#sec-function.prototype.tostring', 'Function.prototype.toString')}}{{Spec2('ESDraft')}} 
+ +

浏览器兼容性

+ +
+ + +

{{Compat("javascript.builtins.Function.toString")}}

+
+ +

附注(针对Firefox)

+ + + +

相关链接

+ + -- cgit v1.2.3-54-g00ecf