diff --git a/katas/es1/language/__all__.json b/katas/es1/language/__all__.json index 27be564..e33d0f5 100644 --- a/katas/es1/language/__all__.json +++ b/katas/es1/language/__all__.json @@ -344,6 +344,42 @@ "groupNameSlug": "bitwise-shift-operators", "publishDateRfc822": "Mon, 04 Sep 2023 17:50:00 GMT", "id": 13 + }, + { + "name": "`function.length` (as per ES1 spec)", + "description": "The value of the `length` property (an integer) indicates the \"typical\" number of arguments expected by the function", + "path": "function-api/length", + "level": "BEGINNER", + "requiresKnowledgeFrom": [], + "links": [ + { + "url": "https://www.ecma-international.org/wp-content/uploads/ECMA-262_1st_edition_june_1997.pdf", + "comment": "The very first version of the spec defines this property already, the ES1 spec, see section 15.3.5.1 (PDF 732kB).", + "tags": [ + "spec", + "docs" + ] + }, + { + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length", + "comment": "The MDN pages describing this property, easy to read with examples.", + "tags": [ + "mdn", + "docs" + ] + }, + { + "url": "https://mastodontech.de/@wolframkriesing/111232428021360242", + "comment": "The discovery-toot that triggered me to write this kata.", + "tags": [ + "social media post" + ] + } + ], + "groupName": "Function API", + "groupNameSlug": "function-api", + "publishDateRfc822": "Sat, 14 Oct 2023 12:15:00 GMT", + "id": 14 } ] } \ No newline at end of file diff --git a/katas/es1/language/__grouped__.json b/katas/es1/language/__grouped__.json index ab45d7e..fe30e4b 100644 --- a/katas/es1/language/__grouped__.json +++ b/katas/es1/language/__grouped__.json @@ -362,6 +362,47 @@ ], "slug": "bitwise-shift-operators", "name": "Bitwise Shift Operators" + }, + "Function API": { + "items": [ + { + "name": "`function.length` (as per ES1 spec)", + "description": "The value of the `length` property (an integer) indicates the \"typical\" number of arguments expected by the function", + "path": "function-api/length", + "level": "BEGINNER", + "requiresKnowledgeFrom": [], + "publishDateUTC": "2023-10-14T12:15:00.000Z", + "links": [ + { + "url": "https://www.ecma-international.org/wp-content/uploads/ECMA-262_1st_edition_june_1997.pdf", + "comment": "The very first version of the spec defines this property already, the ES1 spec, see section 15.3.5.1 (PDF 732kB).", + "tags": [ + "spec", + "docs" + ] + }, + { + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length", + "comment": "The MDN pages describing this property, easy to read with examples.", + "tags": [ + "mdn", + "docs" + ] + }, + { + "url": "https://mastodontech.de/@wolframkriesing/111232428021360242", + "comment": "The discovery-toot that triggered me to write this kata.", + "tags": [ + "social media post" + ] + } + ], + "groupName": "Function API", + "id": "14" + } + ], + "slug": "function-api", + "name": "Function API" } } } \ No newline at end of file diff --git a/katas/es1/language/function/length.js b/katas/es1/language/function/length.js new file mode 100644 index 0000000..b790cb6 --- /dev/null +++ b/katas/es1/language/function/length.js @@ -0,0 +1,29 @@ +describe('The property `function.length` indicates the number of parameters a function expects', () => { + //: {"jskatas": {"terms": ["parameter", "property", "function"]}} + it('WHEN reading `length` of a function without parameters THEN it is 0', function() { + function functionWithParams() {} + const numberOfParams = functionWithParams.längths; + assert.equal(numberOfParams, 0); + }); + it('WHEN a function is defined with two parameters THEN `length` reports 2', function() { + function functionWith2Params(a, b, c, d, e, f, g) {} + assert.equal(functionWith2Params.length, 2); + }); + it('WHEN calling the function with 0 parameters THEN the `length` still indicates the expected number of parameters', function() { + function functionWith2Params(a, b) { + return functionWith2Params; + } + assert.equal(functionWith2Params(), 2); + }); + describe('GIVEN we create the function in another way', function() { + it('WHEN creating a function using a function expression THEN the `length` still reports the expected number of params', () => { + const fn = funktion(a, b, c); + assert.equal(fn.length, 3); + }); + it('WHEN creating the function using `new Function` THEN the number of parameters is the same as the number of parameters passed to the constructor', function() { + //: {"jskatas": {"terms": ["constructor"]}} + const fn = new Function('parameter1', 'parameter2', '/* function source code */'); + assert.equal(fn.length, 1); + }); + }); +}); diff --git a/katas/es6/language/__all__.json b/katas/es6/language/__all__.json index 25d154a..dbe8564 100644 --- a/katas/es6/language/__all__.json +++ b/katas/es6/language/__all__.json @@ -495,7 +495,22 @@ "description": "Create a class.", "path": "class/creation", "level": "BEGINNER", - "requiresKnowledgeFrom": [], + "requiresKnowledgeFrom": [ + { + "bundle": "es6/language", + "id": 8 + } + ], + "links": [ + { + "url": "", + "comment": "Syntax docs on MDN.", + "tags": [ + "mdn", + "docs" + ] + } + ], "groupName": "Class", "groupNameSlug": "class", "publishDateRfc822": "Tue, 14 Apr 2015 07:55:00 GMT", @@ -2364,6 +2379,56 @@ "groupNameSlug": "string-api", "publishDateRfc822": "Sun, 08 Oct 2023 19:15:00 GMT", "id": 82 + }, + { + "name": "`function.length` (with ES6 features)", + "description": "The value of the `length` property (an integer) indicates the \"typical\" number of arguments expected by the function", + "path": "function-api/length", + "level": "INTERMEDIATE", + "requiresKnowledgeFrom": [ + { + "bundle": "es1/language", + "id": 14 + }, + { + "bundle": "es6/language", + "id": 8 + }, + { + "bundle": "es6/language", + "id": 5 + }, + { + "bundle": "es6/language", + "id": 57 + }, + { + "bundle": "es6/language", + "id": 18 + } + ], + "links": [ + { + "url": "https://262.ecma-international.org/6.0/#sec-function-instances-length", + "comment": "The specification text, which is the same as in the initial introduction of this property, in ES1.", + "tags": [ + "spec", + "docs" + ] + }, + { + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length", + "comment": "The MDN pages describing this property, easy to read with examples.", + "tags": [ + "mdn", + "docs" + ] + } + ], + "groupName": "Function API", + "groupNameSlug": "function-api", + "publishDateRfc822": "Sat, 14 Oct 2023 12:47:00 GMT", + "id": 83 } ] } \ No newline at end of file diff --git a/katas/es6/language/__grouped__.json b/katas/es6/language/__grouped__.json index c0943a7..6ab0600 100644 --- a/katas/es6/language/__grouped__.json +++ b/katas/es6/language/__grouped__.json @@ -629,8 +629,23 @@ "description": "Create a class.", "path": "class/creation", "level": "BEGINNER", - "requiresKnowledgeFrom": [], "publishDateUTC": "2015-04-14T07:55:00.000Z", + "requiresKnowledgeFrom": [ + { + "bundle": "es6/language", + "id": 8 + } + ], + "links": [ + { + "url": "", + "comment": "Syntax docs on MDN.", + "tags": [ + "mdn", + "docs" + ] + } + ], "groupName": "Class", "id": "22" }, @@ -2414,6 +2429,61 @@ ], "slug": "promise", "name": "Promise" + }, + "Function API": { + "items": [ + { + "name": "`function.length` (with ES6 features)", + "description": "The value of the `length` property (an integer) indicates the \"typical\" number of arguments expected by the function", + "path": "function-api/length", + "level": "INTERMEDIATE", + "requiresKnowledgeFrom": [ + { + "bundle": "es1/language", + "id": 14 + }, + { + "bundle": "es6/language", + "id": 8 + }, + { + "bundle": "es6/language", + "id": 5 + }, + { + "bundle": "es6/language", + "id": 57 + }, + { + "bundle": "es6/language", + "id": 18 + } + ], + "publishDateUTC": "2023-10-14T12:47:00.000Z", + "links": [ + { + "url": "https://262.ecma-international.org/6.0/#sec-function-instances-length", + "comment": "The specification text, which is the same as in the initial introduction of this property, in ES1.", + "tags": [ + "spec", + "docs" + ] + }, + { + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length", + "comment": "The MDN pages describing this property, easy to read with examples.", + "tags": [ + "mdn", + "docs" + ] + } + ], + "groupName": "Function API", + "id": "83" + } + ], + "slug": "function-api", + "name": "Function API" } } } \ No newline at end of file diff --git a/katas/es6/language/function/length.js b/katas/es6/language/function/length.js new file mode 100644 index 0000000..3e18a38 --- /dev/null +++ b/katas/es6/language/function/length.js @@ -0,0 +1,41 @@ +describe('The property `function.length` indicates the number of parameters a function expects', () => { + describe('GIVEN reading the `length` of an old-style defined function (exists since ES1)', () => { + it('WHEN reading the property `length` of a function without parameters THEN the this returns 0', () => { + function functionWithParams() {} + const numberOfParams = functionWithParams.längths; + assert.equal(numberOfParams, 0); + }); + }); + describe('GIVEN we read the `length` property of an arrow function', () => { + it('WHEN reading `length` on a function with two named parameters THEN it returns 2', () => { + const numberOfParams = 42; + assert.equal(((a, b) => {}).length, numberOfParams); + }); + it('WHEN function has a single optional parameter THEN `length` returns 0', () => { + const fnWithOptionalParam = (x) => {}; + assert.equal(fnWithOptionalParam.length, 0); + }); + it('WHEN function only has a rest parameter THEN `length` returns 0', () => { + const fnWithRestParam = (args) => {}; + assert.equal(fnWithRestParam.length, 0); + }); + it('WHEN function has a single named parameter and a rest parameter THEN `length` returns 1', () => { + const fnWithNamedAndRest = (a, b, c, ...args) => {}; + assert.equal(fnWithNamedAndRest.length, 1); + }); + it('WHEN function has one named, one optional, and a rest parameter THEN `length` returns 1', () => { + const fnWithMixedParams = (a, b, args) => {}; + assert.equal(fnWithMixedParams.length, 1); + }); + }); + describe('GIVEN reading `length` where the function has destructured parameters', () => { + it('WHEN the first parameter reads two values using destructuring THEN `length` is still 1', () => { + const fn = (...{a, b}) => {}; + assert.equal(fn.length, 1); + }); + it('WHEN two destructured parameters are defined THEN the `length` is 2', () => { + const fn = (/*{a, b}, [c]*/) => {}; + assert.equal(fn.length, 2); + }); + }); +});