当前位置: 首页 > news >正文

博客网站开发报告网站空间下载

博客网站开发报告,网站空间下载,咨询类网站模板,大麦网网站建设的功能定位函数的扩展 基本用法 函数参数的默认值 ES6允许为函数的参数设置默认值#xff0c;即直接写在参数定义的后面。 参数变量是默认声明的#xff0c;所以不能用let或const再次声明。下面代码中#xff0c;参数变量x是默认声明的#xff0c;在函数体中#xff0c;不能用let或c…函数的扩展 基本用法 函数参数的默认值 ES6允许为函数的参数设置默认值即直接写在参数定义的后面。 参数变量是默认声明的所以不能用let或const再次声明。下面代码中参数变量x是默认声明的在函数体中不能用let或const再次声明否则会报错。 function foo(x 5) {let x 1; // errorconst x 2; // error } 与解构赋值默认值结合使用 参数默认值可以与解构赋值的默认值结合起来使用。下面代码使用了对象的解构赋值默认值而没有使用函数参数的默认值。只有当函数foo的参数是一个对象时变量x和y才会通过解构赋值而生成。如果函数foo调用时参数不是对象变量x和y就不会生成从而报错。如果参数对象没有y属性y的默认值5才会生效。 function foo({x, y 5}) {console.log(x, y); }foo({}) // undefined, 5 foo({x: 1}) // 1, 5 foo({x: 1, y: 2}) // 1, 2 foo() // TypeError: Cannot read property x of undefined 下面两种写法都对函数的参数设定了默认值区别是写法一函数参数的默认值是空对象但是设置了对象解构赋值的默认值写法二函数参数的默认值是一个有具体属性的对象但是没有设置对象解构赋值的默认值。 // 写法一 function m1({x 0, y 0} {}) {return [x, y]; }// 写法二 function m2({x, y} { x: 0, y: 0 }) {return [x, y]; } 值。// 函数没有参数的情况 m1() // [0, 0] m2() // [0, 0]// x和y都有值的情况 m1({x: 3, y: 8}) // [3, 8] m2({x: 3, y: 8}) // [3, 8]// x有值y无值的情况 m1({x: 3}) // [3, 0] m2({x: 3}) // [3, undefined]// x和y都无值的情况 m1({}) // [0, 0]; m2({}) // [undefined, undefined]m1({z: 3}) // [0, 0] m2({z: 3}) // [undefined, undefined] 个人理解当m1没有传入参数时参数设置为空对象使用对象结构值为{x 0, y 0}当m2没有传入参数时使用设置的默认参数 参数默认值的位置 通常情况下定义了默认值的参数应该是函数的尾参数。因为这样比较容易看出来到底省略了哪些参数。如果非尾部的参数设置默认值实际上这个参数是没法省略的。 // 例一 function f(x 1, y) {return [x, y]; }f() // [1, undefined] f(2) // [2, undefined]) f(, 1) // 报错 f(undefined, 1) // [1, 1]// 例二 function f(x, y 5, z) {return [x, y, z]; }f() // [undefined, 5, undefined] f(1) // [1, 5, undefined] f(1, ,2) // 报错 f(1, undefined, 2) // [1, 5, 2] 如果传入undefined将触发该参数等于默认值null则没有这个效果。 function foo(x 5, y 6) {console.log(x, y); }foo(undefined, null) // 5 null 函数的length属性 指定了默认值以后函数的length属性将返回没有指定默认值的参数个数。也就是说指定了默认值后length属性将失真。 (function (a) {}).length // 1 (function (a 5) {}).length // 0 (function (a, b, c 5) {}).length // 2 因为length属性的含义是该函数预期传入的参数个数。某个参数指定默认值以后预期传入的参数个数就不包括这个参数了。同理rest参数也不会计入length属性。 (function(...args) {}).length // 0 如果设置了默认值的参数不是尾参数那么length属性也不再计入后面的参数了。 (function (a 0, b, c) {}).length // 0 (function (a, b 1, c) {}).length // 1 作用域 下面代码中函数foo的参数x的默认值也是x。这时默认值x的作用域是函数作用域而不是全局作用域。由于在函数作用域中存在变量x但是默认值在x赋值之前先执行了所以这时属于暂时性死区参见《let和const命令》一章任何对x的操作都会报错。 var x 1;function foo(x x) {// ... }foo() // ReferenceError: x is not defined 应用 利用参数默认值可以指定某一个参数不得省略如果省略就抛出一个错误。 function throwIfMissing() {throw new Error(Missing parameter); }function foo(mustBeProvided throwIfMissing()) {return mustBeProvided; }foo() // Error: Missing parameter 上面代码的foo函数如果调用的时候没有参数就会调用默认值throwIfMissing函数从而抛出一个错误。 从上面代码还可以看到参数mustBeProvided的默认值等于throwIfMissing函数的运行结果即函数名之后有一对圆括号这表明参数的默认值不是在定义时执行而是在运行时执行即如果参数已经赋值默认值中的函数就不会运行这与python语言不一样。 另外可以将参数默认值设为undefined表明这个参数是可以省略的。 function foo(optional undefined) { ··· } rest参数 ES6引入rest参数形式为“...变量名”用于获取函数的多余参数这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组该变量将多余的参数放入数组中。 function add(...values) {let sum 0;for (var val of values) {sum val;}return sum; }add(2, 5, 3) // 10 注意rest参数之后不能再有其他参数即只能是最后一个参数否则会报错。 // 报错 function f(a, ...b, c) {// ... } 函数的length属性不包括rest参数。 (function(a) {}).length // 1 (function(...a) {}).length // 0 (function(a, ...b) {}).length // 1 扩展运算符 扩展运算符spread是三个点...。它好比rest参数的逆运算将一个数组转为用逗号分隔的参数序列。 console.log(...[1, 2, 3]) // 1 2 3console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5[...document.querySelectorAll(div)] // [div, div, div] 该运算符主要用于函数调用。 function push(array, ...items) {array.push(...items); }function add(x, y) {return x y; }var numbers [4, 38]; add(...numbers) // 42 上面代码中array.push(...items)和add(...numbers)这两行都是函数的调用它们的都使用了扩展运算符。该运算符将一个数组变为参数序列。 扩展运算符与正常的函数参数可以结合使用非常灵活。 function f(v, w, x, y, z) { } var args [0, 1]; f(-1, ...args, 2, ...[3]); 扩展运算符的应用 合并数组扩展运算符提供了数组合并的新写法。 // ES5 [1, 2].concat(more) // ES6 [1, 2, ...more]var arr1 [a, b]; var arr2 [c]; var arr3 [d, e];// ES5的合并数组 arr1.concat(arr2, arr3); // [ a, b, c, d, e ]// ES6的合并数组 [...arr1, ...arr2, ...arr3] // [ a, b, c, d, e ] 与解构赋值结合扩展运算符可以与解构赋值结合起来用于生成数组。 // ES5 a list[0], rest list.slice(1) // ES6 [a, ...rest] list 下面是另外一些例子。 const [first, ...rest] [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5]const [first, ...rest] []; first // undefined rest // []:const [first, ...rest] [foo]; first // foo rest // [] 如果将扩展运算符用于数组赋值只能放在参数的最后一位否则会报错。 const [...butLast, last] [1, 2, 3, 4, 5]; // 报错const [first, ...middle, last] [1, 2, 3, 4, 5]; // 报错 字符串 扩展运算符还可以将字符串转为真正的数组。 [...hello] // [ h, e, l, l, o ] 正确返回字符串长度的函数可以像下面这样写。 function length(str) {return [...str].length; }实现了Iterator接口的对象 任何Iterator接口的对象都可以用扩展运算符转为真正的数组。下面是一个最特殊的例子。它不是数组而是一个类似数组的对象。这时扩展运算符可以将其转为真正的数组原因就在于NodeList对象实现了Iterator接口。 var nodeList document.querySelectorAll(div); var array [...nodeList]; 对于那些没有部署Iterator接口的类似数组的对象扩展运算符就无法将其转为真正的数组。下面代码中arrayLike是一个类似数组的对象但是没有部署Iterator接口扩展运算符就会报错。这时可以改为使用Array.from方法将arrayLike转为真正的数组。 let arrayLike {0: a,1: b,2: c,length: 3 };// TypeError: Cannot spread non-iterable object. let arr [...arrayLike]; Map和Set结构Generator函数 扩展运算符内部调用的是数据结构的Iterator接口因此只要具有Iterator接口的对象都可以使用扩展运算符比如Map结构。 let map new Map([[1, one],[2, two],[3, three], ]);let arr [...map.keys()]; // [1, 2, 3] Generator函数运行后返回一个遍历器对象因此也可以使用扩展运算符。 var go function*(){yield 1;yield 2;yield 3; };[...go()] // [1, 2, 3] 下面代码中变量go是一个Generator函数执行后返回的是一个遍历器对象对这个遍历器对象执行扩展运算符就会将内部遍历得到的值转为一个数组。 如果对没有iterator接口的对象使用扩展运算符将会报错。 var obj {a: 1, b: 2}; let arr [...obj]; // TypeError: Cannot spread non-iterable object name属性 函数的name属性返回该函数的函数名。 function foo() {} foo.name // foo var func1 function () {};// ES5 func1.name // // ES6 func1.name // func1 const bar function baz() {};// ES5 bar.name // baz// ES6 bar.name // baz 箭头函数 函数体内的this对象就是定义时所在的对象而不是使用时所在的对象对象的扩展 属性的简洁表示法 ES6允许直接写入变量和函数作为对象的属性和方法。这样的书写更加简洁。下面代码表明ES6允许在对象之中直接写变量。这时属性名为变量名, 属性值为变量的值。下面是另一个例子。属性名表达式 ES6 允许字面量定义对象时用表达式作为对象的属性名即把表达式放在方括号内。 let propKey foo;let obj {[propKey]: true,[a bc]: 123 }; 注意属性名表达式与简洁表示法不能同时使用会报错。 // 报错 var foo bar; var bar abc; var baz { [foo] };// 正确 var foo bar; var baz { [foo]: abc}; 注意属性名表达式如果是一个对象默认情况下会自动将对象转为字符串[object Object]这一点要特别小心。下面代码中[keyA]和[keyB]得到的都是[object Object]所以[keyB]会把[keyA]覆盖掉而myObject最后只有一个[object Object]属性。 const keyA {a: 1}; const keyB {b: 2};const myObject {[keyA]: valueA,[keyB]: valueB };myObject // Object {[object Object]: valueB} Object.is() ES5比较两个值是否相等只有两个运算符相等运算符和严格相等运算符。它们都有缺点前者会自动转换数据类型后者的NaN不等于自身以及0等于-0。JavaScript缺乏一种运算在所有环境中只要两个值是一样的它们就应该相等。ES6提出“Same-value equality”同值相等算法用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等与严格比较运算符的行为基本一致。 Object.is(foo, foo) // true Object.is({}, {}) // false//不同之处只有两个一是0不等于-0二是NaN等于自身。0 -0 //true NaN NaN // falseObject.is(0, -0) // false Object.is(NaN, NaN) // true Object.assign() Object.assign方法用于对象的合并将源对象source的所有可枚举属性复制到目标对象target。Object.assign方法的第一个参数是目标对象后面的参数都是源对象。注意如果目标对象与源对象有同名属性或多个源对象有同名属性则后面的属性会覆盖前面的属性。如果只有一个参数Object.assign会直接返回该参数。如果该参数不是对象则会先转成对象然后返回。由于undefined和null无法转成对象所以如果它们作为参数仅限第一个参数就会报错其它参数无法转成对象会直接跳过。 var target { a: 1 };var source1 { b: 2 }; var source2 { c: 3 };Object.assign(target, source1, source2); target // {a:1, b:2, c:3} 其他类型的值即数值、字符串和布尔值不在首参数也不会报错。但是除了字符串会以数组形式拷贝入目标对象其他值都不会产生效果。 var v1 abc; var v2 true; var v3 10;var obj Object.assign({}, v1, v2, v3); console.log(obj); // { 0: a, 1: b, 2: c } 注意点 Object.assign方法实行的是浅拷贝而不是深拷贝。深拷贝实现方式如下 Object.assign(obj2,JSON.parse(JSON.stringify(obj1))) 常见用途 为对象添加属性 class Point {constructor(x, y) {Object.assign(this, {x, y});} } 为对象添加方法 Object.assign(SomeClass.prototype, {someMethod(arg1, arg2) {···},anotherMethod() {···} });// 等同于下面的写法 SomeClass.prototype.someMethod function (arg1, arg2) {··· }; SomeClass.prototype.anotherMethod function () {··· }; 克隆对象 function clone(origin) {return Object.assign({}, origin); } 合并多个对象 const merge (target, ...sources) Object.assign(target, ...sources); 为属性指定默认值 const DEFAULTS {logLevel: 0,outputFormat: html };function processContent(options) {options Object.assign({}, DEFAULTS, options); } 属性的可枚举性 对象的每个属性都有一个描述对象Descriptor用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。 let obj { foo: 123 }; Object.getOwnPropertyDescriptor(obj, foo) // { // value: 123, // writable: true, // enumerable: true, // configurable: true // } 描述对象的enumerable属性称为”可枚举性“如果该属性为false就表示某些操作会忽略当前属性。ES5有三个操作会忽略enumerable为false的属性。 for...in循环只遍历对象自身的和继承的可枚举的属性Object.keys()返回对象自身的所有可枚举的属性的键名JSON.stringify()只串行化对象自身的可枚举的属性ES6新增了一个操作Object.assign()会忽略enumerable为false的属性只拷贝对象自身的可枚举的属性。 这四个操作之中只有for...in会返回继承的属性。实际上引入enumerable的最初目的就是让某些属性可以规避掉for...in操作。比如对象原型的toString方法以及数组的length属性就通过这种手段不会被for...in遍历到。 Object.getOwnPropertyDescriptor(Object.prototype, toString).enumerable // falseObject.getOwnPropertyDescriptor([], length).enumerable // false 上面代码中toString和length属性的enumerable都是false因此for...in不会遍历到这两个继承自原型的属性。另外ES6规定所有Class的原型的方法都是不可枚举的。 Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, foo).enumerable // false 总的来说操作中引入继承的属性会让问题复杂化大多数时候我们只关心对象自身的属性。所以尽量不要用for...in循环而使用Object.keys()代替。 __proto__属性Object.setPrototypeOf()Object.getPrototypeOf() __proto__属性 __proto__属性前后各两个下划线用来读取或设置当前对象的prototype对象。目前所有浏览器包括IE11都部署了这个属性。 // es6的写法 var obj {method: function() { ... } }; obj.__proto__ someOtherObj;// es5的写法 var obj Object.create(someOtherObj); obj.method function() { ... }; 该属性没有写入ES6的正文而是写入了附录原因是__proto__前后的双下划线说明它本质上是一个内部属性而不是一个正式的对外的API只是由于浏览器广泛支持才被加入了ES6。标准明确规定只有浏览器必须部署这个属性其他运行环境不一定需要部署而且新的代码最好认为这个属性是不存在的。因此无论从语义的角度还是从兼容性的角度都不要使用这个属性而是使用下面的Object.setPrototypeOf()写操作、Object.getPrototypeOf()读操作、Object.create()生成操作代替。Object.setPrototypeOf() Object.setPrototypeOf方法的作用与__proto__相同用来设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。 // 格式 Object.setPrototypeOf(object, prototype)// 用法 var o Object.setPrototypeOf({}, null); 该方法等同于下面的函数。 function (obj, proto) {obj.__proto__ proto;return obj; } 下面是一个例子。 let proto {}; let obj { x: 10 }; Object.setPrototypeOf(obj, proto);proto.y 20; proto.z 40;obj.x // 10 obj.y // 20 obj.z // 40 上面代码将proto对象设为obj对象的原型所以从obj对象可以读取proto对象的属性。 Object.getPrototypeOf() 该方法与setPrototypeOf方法配套用于读取一个对象的prototype对象 Object.getPrototypeOf(obj); 下面是一个例子。 function Rectangle() { }var rec new Rectangle();Object.getPrototypeOf(rec) Rectangle.prototype // trueObject.setPrototypeOf(rec, Object.prototype); Object.getPrototypeOf(rec) Rectangle.prototype // false Object.values() Object.values方法返回一个数组成员是参数对象自身的不含继承的所有可遍历enumerable属性的键值。 var obj { foo: bar, baz: 42 }; Object.values(obj) // [bar, 42] 返回数组的成员顺序与《属性的遍历》介绍的排列规则一致。首先遍历所有属性名为数值的属性按照数字排序。其次遍历所有属性名为字符串的属性按照生成时间排序。最后遍历所有属性名为Symbol值的属性按照生成时间排序。 var obj { 100: a, 2: b, 7: c }; Object.values(obj) // [b, c, a] 上面代码中属性名为数值的属性是按照数值大小从小到大遍历的因此返回的顺序是b、c、a。Object.values只返回对象自身的可遍历属性。 var obj Object.create({}, {p: {value: 42}}); Object.values(obj) // [] 上面代码中Object.create方法的第二个参数添加的对象属性属性p如果不显式声明默认是不可遍历的。Object.values不会返回这个属性。Object.values会过滤属性名为Symbol值的属性。 Object.values({ [Symbol()]: 123, foo: abc }); // [abc] 如果Object.values方法的参数是一个字符串会返回各个字符组成的一个数组。 Object.values(foo) // [f, o, o] 上面代码中字符串会先转成一个类似数组的对象。字符串的每个字符就是该对象的一个属性。因此Object.values返回每个属性的键值就是各个字符组成的一个数组。 如果参数不是对象Object.values会先将其转为对象。由于数值和布尔值的包装对象都不会为实例添加非继承的属性。所以Object.values会返回空数组。 Object.values(42) // [] Object.values(true) // [] Object.entries() Object.entries方法返回一个数组成员是参数对象自身的不含继承的所有可遍历enumerable属性的键值对数组。 var obj { foo: bar, baz: 42 }; Object.entries(obj) // [ [foo, bar], [baz, 42] ] 除了返回值不一样该方法的行为与Object.values基本一致。如果原对象的属性名是一个Symbol值该属性会被省略。 对象的扩展运算符 解构赋值 对象的解构赋值用于从一个对象取值相当于将所有可遍历的、但尚未被读取的属性分配到指定的对象上面。所有的键和它们的值都会拷贝到新对象上面。 let { x, y, ...z } { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 } 扩展运算符 扩展运算符...用于取出参数对象的所有可遍历属性拷贝到当前对象之中。 let z { a: 3, b: 4 }; let n { ...z }; n // { a: 3, b: 4 } 扩展运算符可以用于合并两个对象。 let ab { ...a, ...b }; // 等同于 let ab Object.assign({}, a, b); Object.getOwnPropertyDescriptors() ES7有一个提案提出了Object.getOwnPropertyDescriptors方法返回指定对象所有自身属性非继承属性的描述对象。 const obj {foo: 123,get bar() { return abc } };Object.getOwnPropertyDescriptors(obj) // { foo: // { value: 123, // writable: true, // enumerable: true, // configurable: true }, // bar: // { get: [Function: bar], // set: undefined, // enumerable: true, // configurable: true } } Object.getOwnPropertyDescriptors方法返回一个对象所有原对象的属性名都是该对象的属性名对应的属性值就是该属性的描述对象。
http://www.laogonggong.com/news/113711.html

相关文章:

  • dw做的网站与浏览器不匹配山东建设兵团网站
  • 苏醒wordpress百度搜索推广优化师工作内容
  • 网站建设前提wordpress 标签筛选
  • 怀化网站优匿怎么做百度网站验证
  • 汕头做网站的公司asp.net ftp发布网站
  • 网站建设兆金手指下拉php网站连接数据库
  • 兰州金建工程建设监理网站课程网站开发的开题报告
  • 商城网站公司哪里有网站建设流程
  • 阳泉网站建设上海网站建设在哪
  • 技术支持 长沙网站建设-创研科技福州市台江区网站
  • y2学年做的租房网站wordpress帝国哪个安全
  • 网站建设属于无形资产吗更新网站的步骤
  • 网站开发和游戏开发哪个难wordpress表单创建插件
  • 湖北聚四方建设有限公司网站杭州微网站开发
  • 做电影网站量刑标准如何在国外网站上做外贸
  • WordPress网站仿制注册网站英语怎么说
  • 网站建设视频教程phpwordpress问题解决方法
  • vs2015 网站开发这样做网站
  • 公司内部网站建设兰州建设厅评职称网站
  • 创可贴网站怎么做图片大全东莞建设网下载app
  • 一个好的网站是什么样的怎么免费网做百度收录的网站
  • 灵犀科技-网站开发一个平台怎么推广
  • 长沙好的网站建设公司标识标牌设计公司
  • 做一网站要学些什么软件网站维护是不是很难做
  • 门户网站还能建设么个人如何建设网站
  • 郑州建站多少钱保定做网站百度推广
  • 免费自助建站网站一览自助建网站wordpress怎么改登陆
  • 电子商务网站设计原理书籍学做网站需要多久时间
  • 桂林小学网站建设企业如何建公司网站
  • 外贸网站做流量163企业邮箱费用多少