标签:function arguments 函数作用域 let 结构 mic ext 传参 create
2. 定义时可以只声明不赋值
3. 定义之后可以随时修改变量的值
4. 变量声明会被提升
5. 可重复定义变量
6. 全局定义的变量会被作为全局对象(global/window)的属性
7. 在代码块中使用 var 关键字声明的变量不会被束缚在代码块中
1 if (true) { 2 3 var foo, bar = ‘abc‘; 4 } 5 6 console.log(foo, bar)
1 // 0. 可以一次定义多个变量 2 // let foo = 123, bar = ‘abc‘; 3 4 // 1. 定义时可以只声明不赋值 5 // let foo, bar; 6 7 8 // 2. 定义之后可以随时修改变量的值 9 // let foo = 123, bar = ‘abc‘; 10 // foo = ‘abc‘; 11 // bar = 123; 12 // console.log(foo, bar); // ‘abc‘ 123 13 14 // 3. 使用 let 关键字定义的变量,变量声明不会被提升,因此我们需要先定义,后使用 15 // console.log(foo); // foo is not undefined 16 // let foo = 123; 17 18 19 // 4. 在同一作用域下,不能重复定义同名变量 20 // let foo = 123; 21 // let foo = ‘abc‘; // Identifier ‘foo‘ has already been declared 22 // console.log(foo) 23 24 // 5. 全局定义的变量会被作为全局对象(global/window)的属性 25 26 // 6. 在代码块中使用 let 关键字声明的变量会被束缚在代码块中
1. 在使用 const 关键字声明常量时,必须要进行赋值(初始化)。
2. 常量一旦初始化后,就不能被修改。
3. 在同一作用域下,不能重复定义同名的常量。
4. 常量的声明不会被提升
5. 所有常量只在当前代码块内有效,一旦执行流到了代码块外,这些常量就会被立即销毁。
1 <script> 2 3 // 1. 在使用 const 关键字声明常量时,必须要进行赋值(初始化)。 4 // const foo = 123, bar = ‘abc‘; 5 // const bar; // 抛出错误:Missing initializer in const declaration 6 7 // 2. 常量一旦初始化后,就不能被修改。 8 // const foo = 123; 9 // foo = ‘abc‘; // 抛出错误:Assignment to constant variable. 10 11 // 3. 在同一作用域下,不能重复定义同名的常量 12 // const foo = 123; 13 // const foo = ‘abc‘; // 抛出错误:Identifier ‘foo‘ has already been declared 14 15 // 4. 常量的声明不会被提升 16 // console.log(foo) // 抛出错误:foo is not defined 17 // const foo = 123; 18 19 // 5. 所有常量只在当前代码块内有效,一旦执行流到了代码块外,这些常量就会被立即销毁。 20 // if (true) { 21 // const foo = 123; 22 // console.log(foo) 23 // } 24 // console.log(foo) // 抛出错误:foo is not defined 25 26 </script>
1 <script> 2 3 let str1 = ‘你好,世界!‘; 4 let str2 = `Hello 5 World!`; // 可以直接换行 6 let str3 = `Hello ${str1} World!`; // 向模板中插入数据 7 console.log(str3) 8 // 使用场景: 9 10 let students = [ 11 { 12 name: ‘黄聪聪‘, 13 age: 20, 14 gender: ‘男‘ 15 }, 16 { 17 name: ‘赵志刚‘, 18 age: 20, 19 gender: ‘男‘ 20 }, 21 { 22 name: ‘江芦贵‘, 23 age: 20, 24 gender: ‘男‘ 25 } 26 ]; 27 28 let htmls = ‘‘; 29 30 students.forEach(function(student) { 31 htmls += `<tr> 32 <td>${student.name }</td> 33 <td>${student.age }</td> 34 <td>${student.gender}</td> 35 </tr>`; 36 }); 37 38 console.log(htmls) 39 40 41 </script>
1 <script> 2 3 let colors1 = [‘red‘, ‘green‘, ‘blue‘]; 4 5 // 使用展开操作符输出数组中的元素,类似于:console.log(‘red‘, ‘green‘, ‘blue‘) 6 console.log(...colors1) 7 console.log(colors1) //对象 8 9 // 使用场景一:合并数组,将 colors1 中的元素合并到 colors2 中 10 let colors2 = [‘black‘, ‘white‘, ‘purple‘, ...colors1]; 11 console.log(...colors2) 12 // 使用场景二:复制数组 13 let colors3 = [...colors2] 14 console.log(...colors3) 15 </script>
1 <script> 2 // 实参 12 会被赋值给形参 a,剩余的所有实参都会被交给形参 bar,bar 会自动变成一个数组。 3 function foo (a, ...bar) { 4 console.log(a, bar) 5 } 6 7 foo(12, 34, 45, 67, 89) 8 // 注意,剩余操作符只能应用到最后一个形参上,否则会抛出错误:Rest parameter must be last formal parameter 9 // 下面的写法是错误的: 10 // function foo (a, ...bar, b) { 11 // console.log(a, bar, b) 12 // } 13 14 // foo(12, 34, 45, 67, 89) 15 </script>
在 ECMAScript 5 或更早的版本中,从对象或数组中获取特定的数据并赋值给本地变量需要书写很多并且相似的代码。例如:
1 let options = { 2 repeat: true, 3 save: false 4 }; 5 6 // 从对象中提取数据 7 8 let repeat = options.repeat, 9 save = options.save;
这段代码反复地提取在 options 上存储地属性值并将它们传递给同名的本地变量。虽然这些看起来不是那么复杂,不过想象一下如果你的一大批变量有着相同的需求,你就只能一个一个地赋值。而且,如果你需要从对象内部嵌套的结构来查找想要的数据,你极有可能为了一小块数据而访问了整个数据结构。
这也是 ECMAScript 6 给对象和数组添加解构的原因。当你想要把数据结构分解为更小的部分时,从这些部分中提取数据会更容易些。很多语言都能使用精简的语法来实现解构操作
1 <script> 2 3 const obj = { 4 firstName: ‘张康‘, 5 lastName: ‘尼古拉斯‘, 6 myAge: 30, 7 phone: { 8 number: 110, 9 brand: ‘魅族‘, 10 color: ‘黑色‘ 11 } 12 }; 13 14 // 1. 使用对象解构初始化同名变量 15 // 告诉 obj 对象,把 firstName 属性的值赋值给同名变量 firstName,把 lastName 属性的值赋值给同名变量 lastName 16 // let { firstName, lastName } = obj; 17 // console.log(firstName, lastName) // ‘张康‘ ‘尼古拉斯‘ 18 19 // 2. 使用对象解构初始化非同名变量 20 // 告诉 obj 对象,把 firstName 属性的值赋值给变量 first_name,把 lastName 属性的值赋值给变量 last_name 21 22 // let { firstName: first_name, lastName: last_name } = obj; 23 // console.log(first_name, last_name) // ‘张康‘ ‘尼古拉斯‘ 24 25 // 3. 为变量指定默认值 26 // 当 obj 对象中没有 myAge 属性时,变量 myAge 默认会被赋值为 20 27 // let { firstName, lastName, myAge = 20 } = obj; 28 // console.log(firstName, lastName, myAge) // ‘张康‘ ‘尼古拉斯‘ 30 29 30 // 当 obj 对象中没有 myAge 属性时,变量 my_age 默认会被赋值为 20 31 // let { firstName: first_name, lastName: last_name, myAge: my_age = 20} = obj; 32 // console.log(first_name, last_name, my_age) // ‘张康‘ ‘尼古拉斯‘ 30 33 34 // 4. 使用对象解构为已有变量重新赋值 35 // let first_name = ‘郭帅‘, last_name = ‘莱昂纳多‘; 36 37 // JS 解析引擎不允许赋值操作符(=)左边出现花括号,但是可以使用小括号将整个赋值语句包裹起来,这样一来,整个赋值语句就变成了一个表达式。 38 // ({ firstName: first_name, lastName: last_name } = obj); 39 // console.log(first_name, last_name) // ‘张康‘ ‘尼古拉斯‘ 40 41 // 5. 嵌套对象解构 42 // 告诉 obj 对象,把 phone 对象中的 number 属性的值赋值给变量 number,把 phone 对象中的 brand 属性的值赋值给变量 brand 43 // let { phone: { number, brand } } = obj; 44 // console.log(number, brand) 45 46 </script>
1 <script> 2 3 const colors = [‘red‘, ‘green‘, ‘blue‘, ‘orange‘, [ ‘black‘, ‘white‘ ] ]; 4 5 // 1. 使用数组解构初始化变量 6 // 数组中的元素会按照顺序赋值给这 3 个变量 7 // let [ firstColor, secondColor, thirdColor ] = colors; 8 // console.log(firstColor, secondColor, thirdColor) 9 10 // 2. 使用数组解构为变量重新赋值 11 // let firstColor = ‘black‘, secondColor = ‘white‘; 12 // 数组中的元素会按照顺序赋值给这 2 个变量 13 // [ firstColor, secondColor ] = colors; 14 // console.log(firstColor, secondColor) 15 16 // 3. 为变量指定默认值 17 // 当数组中没有第 4 个元素时,变量 fourthColor 会被赋值成默认值 ‘pink‘ 18 // let [ firstColor, secondColor, thirdColor, fourthColor = ‘pink‘ ] = colors; 19 // console.log(firstColor, secondColor, thirdColor, fourthColor) 20 21 // 4. 跳过数组中的指定元素 22 // let [ firstColor, , ,fourthColor ] = colors; 23 // console.log(firstColor, fourthColor) 24 25 // 5. 嵌套数组解构 26 let [,,,,[nestedFirstColor, nestedSecondColor]] = colors; 27 console.log(nestedFirstColor, nestedSecondColor) 28 29 30 </script>
1 <script> 2 3 let node = { 4 type: ‘Identifier‘, 5 name: ‘foo‘, 6 loc: { 7 start: { 8 line: 1, 9 column: 1 10 }, 11 end: { 12 line: 4, 13 column: 4 14 } 15 }, 16 range: [0, 3] 17 }; 18 19 // 把 node 对象中 loc 对象的 start 属性的值赋值给变量 start,把 range 数组中第 2 个元素赋值给变量 endIndex 20 let { loc: { start }, range: [, endIndex] } = node; 21 22 console.log(start, endIndex) 23 24 </script>
1 <script> 2 // 1. 以普通方式传参时,相当于把 obj 对象赋值给形参 student 3 // student = obj 4 5 // function getFullName (student) { 6 // return student.firstName + ‘ · ‘ + student.lastName; 7 // } 8 9 // let obj = { 10 // firstName: ‘刘旭凯‘, 11 // lastName: ‘约翰尼‘ 12 // }; 13 14 // console.log(getFullName(obj)) 15 16 17 // 2. 以对象解构的方式传参 18 // 把 obj 对象中的 firstName 属性的值传递给形参 firstName,把 lastName 属性的值传递给形参 lastName 19 // { firstName, lastName } = obj; 20 21 // function getFullName ({ firstName, lastName }) { 22 // return firstName + ‘ · ‘ + lastName; 23 // } 24 25 // let obj = { 26 // firstName: ‘刘旭凯‘, 27 // lastName: ‘约翰尼‘ 28 // }; 29 30 // console.log(getFullName(obj)) 31 32 // 3. 为形参指定默认值 33 // 当 obj 对象没有 lastName 属性时,形参 lastName 就会使用默认值 ‘尼古拉斯‘ 34 function getFullName ({ firstName, lastName = ‘尼古拉斯‘ }) { 35 return firstName + ‘ · ‘ + lastName; 36 } 37 38 let obj = { 39 firstName: ‘刘旭凯‘, 40 lastName: ‘克里斯蒂安‘ 41 }; 42 43 console.log(getFullName(obj)) 44 45 46 </script>
ES5 语法中,为函数形参指定的默认值写法
1 <script> 2 // 1. 在 ES5 语法中,为函数形参指定默认值的写法: 3 // 写法一: 4 function foo (bar) { 5 bar = bar || ‘abc‘; 6 console.log(bar) 7 } 8 foo(‘xyz‘) 9 10 // 写法二: 11 function foo (bar) { 12 if (typeof bar === ‘undefined‘) { 13 bar = ‘abc‘; 14 } 15 console.log(bar) 16 } 17 18 foo(‘xyz‘); 19 20 21 22 </script>
ES6中为函数形参指定默认值
a.除了为形参直接指定默认值以外,形参的默认值还可以是表达式,例如,timeout = 5 * 1000
b.在预编译阶段,形参表达式不会执行,只有在调函函数,并且没有为形参传递实参的情况下才执行
1 <script> 2 // 2. 使用 ES6 的语法为函数形参指定默认值 3 function post (url, data = {}, timeout = foo * 1000) { 4 console.log(arguments) 5 console.log(url, data, timeout) 6 } 7 8 // post(‘xyz‘, {uname: ‘zhangsan‘, upass: ‘123‘}, 3000); 9 post(‘xyz‘, null, 3000); 10 11 // 注意事项: 12 // 1> 除了为形参直接指定默认值以外,形参的默认值还可以是表达式,例如,timeout = 5 * 1000 13 // 2> 在预编译阶段,形参表达式不会执行,只有在调函函数,并且没有为形参传递实参的情况下才执行。 14 15 </script>
1 <script> 2 3 // 不定参数,使用剩余操作符接收剩余的实参,这些实参会被保存到一个不定参数(args)中 4 function foo (...args) { 5 return args.reduce(function (previousValue, currentValue) { 6 console.log(previousValue, currentValue) 7 return previousValue += currentValue; 8 }) 9 } 10 11 // 将上面的函数改成箭头函数的形式 12 var foo = (...args) => args.reduce((a, b) =>a += b) 13 14 15 console.log(foo(1, 32, 34, 5, 6)) 16 17 </script>
previousValue:上一个值
currentValue:当前的值
reduce()方法:
1.接收一个函数作为累加器,将数组元素计算为一个值(从左到右),
2.需要接收四个参数( 必需:1.acc 累加器 2.cur 当前值 ;可选:1.idx 当前索引 2 .src 源数组)
省略等号和function
如果形参的数量为 1,则可以省略小括号。
如果形参数量大于 1,则不能省略小括号。
如果函数的执行体比较简单(直接量或表达式),可以省略大括号,箭头后面的直接量或表达式会被自动作为返回值
如果函数的执行体比较复杂,则不能省略大括号。
1 <script> 2 // 1. 形式一: 3 // var foo = function () { 4 // return ‘Hello World!‘; 5 // }; 6 7 // 如果形参数量为 0,则必须加上小括号。箭头后面的表达式的结果会被作为函数的返回值。 8 // var foo = () => { 9 // return ‘Hello World!‘; 10 // } 11 12 // 2. 形式二: 13 // var foo = function (greeting) { 14 // return greeting; 15 // } 16 17 // 如果形参的数量为 1,则可以省略小括号。 18 // var foo = greeting => { 19 // return greeting; 20 // } 21 22 // 3. 形式三: 23 // var foo = function (firstName, lastName) { 24 // return firstName + ‘ · ‘ + lastName; 25 // } 26 27 // 如果形参数量大于 1,则不能省略小括号。 28 // var foo = (firstName, lastName) => { 29 // return firstName + ‘ · ‘ + lastName; 30 // } 31 32 // 4. 形式四: 33 // var foo = function (a, b) { 34 // return a > b ? a : b; 35 // } 36 37 // 如果函数的执行体比较简单(直接量或表达式),可以省略大括号,箭头后面的直接量或表达式会被自动作为返回值。 38 // var foo = (a, b) => a > b ? a : b; 39 40 // 5. 形式五: 41 // var foo = function (a, b) { 42 // let max = a; 43 // if (b > a) { 44 // max = b; 45 // } 46 // return max; 47 // } 48 49 // 如果函数的执行体比较复杂,则不能省略大括号。 50 // var foo = (a, b) => { 51 // let max = a; 52 // if (b > a) { 53 // max = b; 54 // } 55 // return max; 56 // } 57 // console.log(foo(‘贾树华‘, ‘尼古拉斯‘)) 58 59 60 61 </script>
普通函数作用域中的 this 已经被绑定成 window 对象,因此当我们放问 this 时,直接在当前作用域下就能访问的到。
箭头函数的作用域中没有绑定 this,因此,当我们访问 this 时,会去上一层作用域中查找 this。
1 <script> 2 3 // 普通函数作用域中的 this 已经被绑定成 window 对象,因此当我们放问 this 时,直接在当前作用域下就能访问的到。 4 // var foo = function () { 5 // console.log(this) 6 // return ‘Hello World!‘; 7 // }; 8 9 // 箭头函数的作用域中没有绑定 this,因此,当我们访问 this 时,会去上一层作用域中查找 this。 10 // var bar = () => { 11 // console.log(this) 12 // return ‘Hello World!‘; 13 // }; 14 15 16 // 示例,由于 sayName 箭头函数中没有绑定 this,因此我们访问 this 时,会去全局作用域中查找。 17 // 查找的结果是 this 指向 window,因此输出的 name 的值是 ‘常军辉‘ 18 19 // var name = ‘常军辉‘; 20 // var obj = { 21 // name: ‘吕鑫洋‘, 22 // sayName: function () { 23 // // this = obj 24 // return this.name; 25 // } 26 // }; 27 28 // console.log(obj.sayName()) 29 30 31 32 </script>
1 <script> 2 3 // 普通函数 4 var foo = function (greeting) { 5 console.log(arguments) 6 return greeting; 7 }; 8 9 // 箭头函数中没有绑定 arguments 对象,因此下面的输入语句会报错:arguments is not defined 10 var bar = (greeting) => { 11 console.log(arguments) 12 return greeting;0 13 }; 14 15 console.log(foo(‘Hello World!‘)) 16 console.log(bar(‘你好世界!‘)) 17 18 </script>
1 <script> 2 3 // this 指向的对象 4 var obj = { 5 fullName: ‘谭文华‘ 6 }; 7 8 // 1. 普通函数,可以使用 call() 方法改变函数中 this 的绑定 9 // var foo = function (greeting) { 10 // return this.fullName + ‘说:‘ + greeting; 11 // }; 12 // console.log(foo.call(obj, ‘Hello World!‘)) 13 14 15 // 2. 箭头函数,不能使用 call() 方法改变函数中 this 的绑定,箭头函数中不能绑定 this。 16 var bar = (greeting) => { 17 return this.fullName + ‘说:‘ + greeting; 18 }; 19 20 // 下面的代码不会报错,但是也不起作用 21 console.log(bar.call(obj, ‘你好世界!‘)) 22 23 </script>
1 <script> 2 // 1. ECMAScript 5 中判断构造函数是否通过 new 关键字调用的写法 3 // function Person (fullName) { 4 // if (this instanceof Person) { 5 // this.fullName = fullName; 6 // } else { 7 // return new Person(fullName); 8 // } 9 // } 10 11 // let student = Person(‘孟天乐‘) 12 13 // 2. ECMASript 6 引入一个 new.target 属性,当我们使用 new 操作符调用构造函数时,new.target 属性的值为构造函数,否则为 undefined 14 // function Person (fullName) { 15 // if (typeof new.target !== ‘undefined‘) { 16 // this.fullName = fullName; 17 // } else { 18 // throw new Error(‘必须通过 new 关键字来调用 Person。‘); 19 // } 20 // } 21 // let student = new Person(‘孟天乐‘); 22 // console.log(student) 23 24 // 3. 除此之外,还可以检查 new.target 是否被某个特定构造函数所有调用。 25 // 例如,Person 构造函数中的 new.target 属性的值被限定为 Person 26 // function Person (fullName, age) { 27 // if (typeof new.target === Person) { 28 // this.fullName = fullName; 29 // this.age = age; 30 // } else { 31 // throw new Error(‘必须通过 new 关键字来调用 Person。‘); 32 // } 33 // } 34 35 // function Dog (fullName, age) { 36 // Person.call(this, fullName, age) 37 // } 38 39 // let dog = new Dog(‘HeHe‘, 3) 40 41 // console.log(dog) 42 43 // 4. 不能在函数外部使用 new.target,否则会报错 44 function Person () { 45 console.log(new.target) 46 } 47 48 // 下面代码会抛出错误:new.target expression is not allowed here 49 // console.log(new.target) 50 51 let student = new Person(‘崔景龙‘) 52 53 </script>
1 <script> 2 3 let fullName = ‘杨柯‘, age = 19; 4 5 let obj = { 6 fullName: fullName, 7 age: age 8 }; 9 10 // 1. 当一个对象的属性与本地变量同名时,不需要再写冒号和值,直接写属性名即可。 11 let obj = { 12 fullName, 13 age 14 }; 15 16 17 </script>
1 <script> 2 3 4 // 在 ES 5 中,如果为对象添加方法,必须要通过指定名称并完整定义函数来实现。 5 let obj = { 6 fullName: ‘杨柯‘, 7 sayName: function () { 8 return this.fullName; 9 } 10 }; 11 12 // 在 ES 6 中,语法更简洁,取消了冒号和 function 关键字。如下所示: 13 let obj = { 14 fullName: ‘杨柯‘, 15 sayName () { 16 return this.fullName; 17 } 18 }; 19 20 21 </script>
1 <script> 2 3 // 在对象字面量中使用方括号表示该属性名是可计算的,方括号中的内容会被计算求值,最终转化成一个字符串,该字符串就是最终的属性名。 4 let suffix = ‘name‘; 5 6 let person = { 7 [‘first‘ + suffix]: ‘杨帅‘, 8 [‘last‘ + suffix]: ‘泰坦尼‘ 9 }; 10 11 console.log(person) 12 13 </script>
1 <script> 2 3 4 // 1. 在有些情况下,既是全等运算符比较出来的结果也是不正确的。例如,在下面两种情况下: 5 6 // +0 和 -0 在 JS 解析引擎中被表示为两个完全不同的实体,而如果使用全等运算符(===)对两者进行比较,得到的结果是两者相等。 7 console.log(+0 == -0); // true 8 console.log(+0 === -0); // true 9 console.log(Object.is(+0, -0)); // false 10 11 // NaN 和 NaN 在 JS 解析引擎中被表示为两个完全相同的实体,但是无论使用等于(==)还是全等(===),得到的结果都是 false。 12 console.log(NaN == NaN); // false 13 console.log(NaN === NaN); // false 14 console.log(Object.is(NaN, NaN)); // true 15 16 // 在大多数情况下,Object.is() 方法的比较结果与全等运算符完全相同,唯一的区别在于 +0 和 -0 会被识别为不相等,NaN 和 NaN 会被识别为相等。 17 18 // 2. Object.assign() 方法可以接收任意数量的源对象(obj2,obj3),并按照指定的顺序将属性复制到接收对象(obj1)。 19 // 如果多个源对象具有同名属性,则排位靠后的源对象会覆盖排外靠前的对象。 20 21 let obj1 = { 22 fullName: ‘陈世壮‘, 23 sayName () { 24 return this.fullName; 25 } 26 }; 27 28 let obj2 = { 29 fullName: ‘任俊玖‘, 30 age: 20 31 }; 32 33 let obj3 = { 34 fullName: ‘朱亚鹏‘, 35 gender: ‘男‘ 36 }; 37 38 // 通过自定义方法实现了一个可以合并多个对象的方法, 39 // function mixin(receiver, ...suppliers) { 40 // suppliers.forEach(supplier => { 41 // Object.keys(supplier).forEach(key => { 42 // receiver[key] = supplier[key] 43 // }) 44 // }) 45 // return receiver; 46 // } 47 // console.log(mixin(obj1, obj2, obj3)) 48 49 // 使用 ES6 新增 Object.assgin() 方法将多个对象的属性合并到第一个对象中。 50 // Object.assign(obj1, obj2, obj3); 51 52 // console.log(obj1) 53 // console.log(obj2) 54 // console.log(obj3) 55 56 57 58 </script>
1 <script> 2 3 // 对于每一组重复属性,都会选取最后一个取值。 4 let obj = { 5 fullName: ‘陈世壮‘, 6 fullName: ‘李忠易‘, 7 age: 18, 8 age: 20 9 }; 10 11 console.log(obj.fullName); // ‘李忠易‘ 12 console.log(obj.age); // 20 13 14 </script>
1 <script> 2 3 // ES 5 中并没有定义对象属性的枚举顺序,有 JavaScript 引擎厂商自行决定。 4 // ES 6 中明确规定了对象的自有属性被枚举时的返回顺序。 5 // 自有属性枚举顺序的基本规则: 6 // 1. 所有数字按升序 7 // 2. 所有字符串按照它们被加入对象时的顺序排序 8 9 let obj = { 10 a: 1, 11 0: 2, 12 c: 3, 13 2: 4, 14 b: 5, 15 1: 6 16 }; 17 18 console.log(Object.getOwnPropertyNames(obj)); // ["0", "1", "2", "a", "c", "b"] 19 20 </script>
1 <script> 2 3 let person = { 4 getGreeting () { 5 return ‘Hello‘; 6 } 7 }; 8 9 let dog = { 10 getGreeting () { 11 return ‘woof‘; 12 } 13 }; 14 15 // 使用 create() 方法将 person 对象作为原型对象 16 let friend = Object.create(person); // {} 17 console.log(friend.getGreeting()); // ‘Hello‘ 18 console.log(Object.getPrototypeOf(friend) === person); // true 19 20 // 使用 setPrototypeOf() 方法将 friend 对象的原型对象修改成 dog 21 Object.setPrototypeOf(friend, dog); 22 console.log(friend.getGreeting()); // ‘Hello‘ 23 console.log(Object.getPrototypeOf(friend) === dog); // true 24 25 </script>
1 <script> 2 3 let person = { 4 getGreeting () { 5 return ‘Hello‘; 6 } 7 }; 8 9 let dog = { 10 getGreeting () { 11 return ‘woof‘; 12 } 13 }; 14 15 // let friend = { 16 // getGreeting () { 17 // return Object.getPrototypeOf(this).getGreeting.call(this) + ‘, hi‘; 18 // } 19 // }; 20 21 // ES 6 引入了 super 关键字,super 指向当前对象的原型对象,实际上也就是 Object.getPrototypeOf(this) 的值,于是,上面的代码可以简化成如下形式: 22 let friend = { 23 getGreeting () { 24 return super.getGreeting() + ‘, hi‘; 25 } 26 }; 27 28 // 使用 setPrototypeOf() 方法将 friend 对象的原型对象修改成 person 29 Object.setPrototypeOf(friend, person); 30 console.log(friend.getGreeting()); // ‘Hello‘ 31 console.log(Object.getPrototypeOf(friend) === person); // true 32 33 // 使用 setPrototypeOf() 方法将 friend 对象的原型对象修改成 dog 34 Object.setPrototypeOf(friend, dog); 35 console.log(friend.getGreeting()); // ‘Hello‘ 36 console.log(Object.getPrototypeOf(friend) === dog); // true 37 38 39 40 </script>
1 <script> 2 3 // 构造函数类似于面向对象编程语言中类(class) 4 function PersonType(fullName) { 5 this.fullName = fullName; 6 } 7 8 Object.defineProperty(PersonType.prototype, ‘sayName‘, { 9 configurable: true, 10 enumerable: false, 11 writable: true, 12 value: function () { 13 return this.fullName; 14 } 15 }) 16 17 let student1 = new PersonType(‘苑文浩‘); 18 19 console.log(student1) 20 21 22 </script>
1 <script> 2 3 // 使用 class 关键字定义 PersonClass 类 4 class PersonClass { 5 // PersonClass 类的构造函数,等价于构造函数 PersonType 6 // 当我们创建 PersonClass 的实例时,该方法会自动被调用。 7 constructor(fullName) { 8 this.fullName = fullName; 9 } 10 11 // 为原型对象添加的方法,等于下面的代码: 12 // Object.defineProperty(PersonType.prototype, ‘sayName‘, { 13 // configurable: true, 14 // enumerable: false, 15 // writable: true, 16 // value: function () { 17 // return this.fullName; 18 // } 19 // }) 20 21 sayName() { 22 return this.fullName; 23 } 24 } 25 26 let student1 = new PersonClass(‘刘旭凯‘); 27 28 console.log(student1) 29 30 // 通过与之前的构造函数对比,类和构造函数的作用是一样的。 31 // 其实类的语法只是一种语法糖,实质上等价于一个自定义类型的构造函数。 32 33 </script>
标签:function arguments 函数作用域 let 结构 mic ext 传参 create
原文地址:https://www.cnblogs.com/wszzj/p/11986376.html