object.assign()
这个方法回使源对象上的[[Get]]取得属性的值,然后使用目标对象上的[[Set]]设置属性的值
实际上对每个源对象执行的是浅复制,如果多个源对象都有相同的属性,则使用最后一个赋值的值
let obj1 = { get a() { return 'aaa' } } let obj2 = { set a(val) { console.log(val) } } console.log(obj1.a) //'aaa' // 对象引用 let obj1 = {}; let obj2 = { a:{} } Object.assign(obj1, obj2) console.log( obj1.a===obj2.a ) //true // 错误处理 let obj1 = {} let obj2 = { a: 1, get b() { throw new Error(); }, c: 3 } try { Object.assign(obj1, obj2) } catch (e) { } console.log(obj1) //{a:1} // 因此在抛出错误之前,目标对象上已经完成的修改会继续存在
Object.is()
和===很像,接收两个参数
console.log(+0 === -0) //true console.log(+0 === 0) //true console.log(-0 === 0) //true // 判断NaN console.log(NaN === NaN)//false console.log(isNaN(NaN))//true // 用object.is()轻松解决 console.log(Object.is(NaN, NaN))//true console.log(Object.is(+0, -0))//false // 要检查超过两个值,利用递归即可 function deep(x, ...rest) { // 传入的值为 1,[1,1,4]; 1,[1,4] ; 1,[4] return Object.is(x, rest[0]) && (rest.length < 2 || deep(...rest)) } let a = deep(1, 1, 1, 4) console.log(a) //false
es6增强的对象语法
//1, 属性名简写 let a = 1; let obj = {a}; console.log(obj) //{a:1} // 代码压缩程序会在不同的作用域间保留属性名,以防找不到引用 ------这句话还不理解 //2,可计算属性 // 有了计算属性,就可以在对象字面量中完成动态属性赋值.中括号运算符包围 //的对象属性键告诉运行时将其作为JavaScript表达式而不是字符串来求职 // 例 const a = 'name'; const b = 'sex'; const c = 'age'; let obj = { [a]: '小红', [b]: '女', [c]: 10 } console.log(obj) //{name:'小红',sex:'女',age:10} // 当然[]里也可以是一个复杂的函数 // 3,简写方法名 let obj = { // 旧的写法 oldName: function (a) { console.log(a) }, //新的写法 newName(a) { console.log(a) } }
解构赋值
// 解构在内部使用ToObject()把源数据结构转换为对象。这也意味着 //在对象结构的上下文中,原始值会被当成对象,这也意味着 // (根据ToObject()的定义),null和undefined不能被结构,否则会抛出错误。 // 例 let { length } = 'foobar'; let { constructor } = 'foobar' // // 这里一定要切记 源对象转为对象就能看懂了 console.log(length, constructor) //6,ƒ String() { [native code] } console.log(constructor === String) //true
//嵌套结构 //解构可以使用嵌套结构,以匹配嵌套的属性: let obj = { name: '小明', age: 11, job: { title: 'web前端' } } let { job: { title } } = obj console.log(title) // web前端
// 参数解构---对参数进行解构不会影响arguments对象 let data = { b: 2, c: 3 } function aaa(a, { b, c }, d) { console.log(arguments) // 1,[2,3],4 console.log(b, c) // 2,3 } aaa(1, data, 2)
try catch 语句
如果try中的代码没有出错,则程序正常运行try中的内容后,不会执行catch中的内容,
如果try中的代码一但出错,程序立即跳入catch中去执行代码,那么try中出错代码后的
所有代码就不再执行了.
try { ({ name: p, work: c, job: b } = obj) } catch (e) { } console.log(p, c, b)
工厂函数
这种工厂模式虽然可以解决创建多个类似对象的问题,但没有解
决对象标识问题(即新创建的对象是什么类型)
function createPerson(name, age, sex) { let o = new Object(); o.name = name; o.age = age; o.sex = sex; o.say = function () { console.log(`大家好,我的名字叫---${name}`) } return o } let p1 = createPerson('小明', 11, '男') p1.say() let p2 = createPerson('小红', 10, '女')
构造函数
定义构造函数可以确保实例被标识为特定类型
构造函数也是函数,和普通函数的唯一区别在于调用方式不同
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.job = 'web'; this.say = function () { console.log(`大家好,我的名字叫---${name}`) } } const p3 = new Person('小刚', 11, '男'); // 不传参的情况下,可以不加括号,只要有new操作符,就可以调用对应的构造函数
构造函数和工厂函数的区别
1、没有明显的创建对象
2、属性和方法直接赋值给了this
3、没有return
构造函数需要注意的事项?
首字母大写,有助于和普通函数进行区分。
要创建Person实例,需要使用new操作符,以这种方式调用构造函数会进行如下操作。
1> 在内存中创建一个新对象;
2> 这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性。
3> 构造函数内部的this被赋值为这个新对象(即this指向新对象)。
4> 执行构造函数内部的代码(给新对象添加属性)
5> 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。 ——————不太明白
原型模式
每个函数都会创建prototype属性,这个属性是一个对象,
包含应该由特定引用类型的实例共享的属性和方法。
好处是 在它上面的属性或方法可以被对象实例共享
console.log(Person.prototype) Person.prototype.say = function () { console.log(`我是原型上的方法${this.name}`) } console.log(p4)
高阶函数
符合以下一个条件即可
若A函数,接收到的参数是一个函数,那么A就可以称之为高阶函数。
若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
常见的有Promist setTimeout 、arr.map()……
函数的柯里化
通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
例 :
function aaa(a){ return function bbb(b){ return function ccc(c){ return a+b+c } } } d=aaa(1)(2)(3) console.log(d)
纯函数
一类特别的函数:只要是同样的输入(实参),必定得到同样的输出(返回)
必须遵守以下一些约束
不得改写数据
不会产生任何副作用,例如网络请求,输入和输出设备
不能调用Date.now()或者Math.random()等不纯的方法