javascript

120 阅读3分钟

构造函数

  • new 关键字来调用的函数叫做构造函数;首字母一般大写。
  • 是一个特殊函数,主要用来初始化对象(为对象变量赋初始值);
  • 这样我们就可以通过一个构造函数创建多个对象,这些对象拥有相同的构造,都可以使用这个构造函数的方法和属性。
  function Person(name, age) {
        console.log(this)
        this.name = name;
        this.age = age;
    }

原型和原型链

js中万物皆对象;

  • 对象又分为普通对象(Object)和函数对象(Function)
  • 任何对象都具有隐式原型属性(__proto__),只有函数对象有显式原型属性(prototype)。

基本类型

undefined、null、Boolean、number、String、symbol(防止属性名的冲突;用法:let sy = Symbol("KK");)

引用类型

统称为object类型,细分的话有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等。

原型

  1. 所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
  2. 所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
  3. 所有引用类型的__proto__属性指向它构造函数的prototype
 function proto() {
        let a = [1, 2, 3];
        console.log(a.__proto__  === Array.prototype)//true
    }
  proto()

原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找(即它的构造函数的prototype),如果还没有找到就会再在构造函数的prototype__proto__中查找(即构造函数.prototype.__proto__),这样一层一层向上查找就会形成一个链式结构,我们称为原型链

function Parent(month){
    this.month = month;
}

var child = new Parent('Ann');

console.log(child.month); // Ann

console.log(child.father); // undefined

在child中查找某个属性时,会执行下面步骤: image.png 访问链路为: image.png

  1. 一直往上层查找,直到到null还没有找到,则返回undefined
  2. Object.prototype.__proto__ === null
  3. 所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象

继承

原型继承

构造函数继承

回调函数

立即执行函数

js中函数的两种命名方式,即表达式声明式

  1. 函数的声明式写法为:function foo(){ }

这种写法会导致函数提升,所有function关键字都会被解释器优先编译,不管是声明在什么位置,都可以调用它,但是它本身不会被执行,定义只是让解释器知道其存在,只有在被调用的时候才会执行

  1. 函数的表达式写法为:var foo=function(){ }

这种写法不会导致函数提升,于是就必须先声明,再调用,否则会出错

(function () {}())
(function () {})()

浅克隆、深克隆

function clone() {
        console.log('------------------clone-------------------')
        // Object.assign实现浅拷贝
        let a = { age: 1 }
        let b = Object.assign({}, a);// Object.assign只会拷贝所有的属性值到新的对象中,如果属性值是对象的话,拷贝的是地址,所以并不是深拷贝。
        a.age = 2
        console.log(b.age, 'Object.assign实现浅拷贝')//1

        // 展开运算符...来实现浅拷贝
        let c = { ...a }
        a.age = 3
        console.log(c.age, '运算符...来实现浅拷贝')//1


        //深克隆(浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,使用深拷贝)
        let deepObj = { name: 1, age: { num: 999, sex: undefined } }
        let clone = { ...deepObj }
        deepObj.age.num = 888
        console.log(clone.age, '浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,使用深拷贝')//888

        let deepObjaaa = { name: 1, age: { num: 999, sex: undefined } }
        let jsonDeepClone = JSON.parse(JSON.stringify(deepObjaaa))
        deepObjaaa.age.num = 888
        // 会忽略undefined
        // 会忽略symbol
        // 不能序列化函数
        // 不能解决循环引用的对象
        console.log(jsonDeepClone.age, '通常可以通过JSON.parse(JSON.stringify(object))来解决')//999

        console.log('------------------clone-------------------')
    }
    clone()

数组去重

function arrFn() {
        console.log('------------------unique-------------------')
        let arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false,
            undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}, { a: 1 }, { a: 1 }];

        // set去重 不会过滤对象
        // let arrSet = Array.from(new Set(arr)) 和arrSet1一样
        // console.log(arrSet, 'set去重')
        let arrSet1 = [...new Set(arr)]
        console.log(arrSet1, 'set去重')

        // for循环去重
        let arrcopy = [...arr]
        for (let i = 0; i < arrcopy.length; i++) {
            for (let j = i + 1; j < arrcopy.length; j++) {
                if (arrcopy[i] === arrcopy[j]) {
                    arrcopy.splice(j, 1);
                    j--
                }
            }
        }
        console.log(arrcopy, 'for循环去重')
        console.log('------------------unique-------------------')
    }
    arrFn()