1-什么是构造函数?
构造函数是bai一种特殊的成du员函数,它主要用于为zhi对象分配存储空dao间,对数据成员进行初始zhuan化shu.构造函数具有一些特殊的性质:
(1)构造函数的名字必须与类同名;
(2)构造函数没有返回类型,它可以带参数,也可以不带参数;
(3)声明类对象时,系统自动调用构造函数,构造函数不能被显式调用;
(4)构造函数可以重载,从而提供初始化类对象的不同方法;
(5)若在声明时未定义构造函数,系统会自动生成默认的构造函数,此时构造函数的函数体为空.
2-创建对象的方式有哪些?举例说明
调用对象的构造函数创建对象 var obj = new Object(); obj.name = "小苏"; obj.eat = function(){ console.log('喜欢吃好吃的') } console.log(obj.name) obj.eat() 工厂函数和new Object()创建对象 function createObj(name){ var obj = new Object(); obj.name = name ; obj.zsyz = function(){ console.log('建筑卡') } return obj } var aa = createObj("小憨憨") console.log(aa) 使用字面量形式创建对象 var obj = { name:'sun', SayHi:function(){ console.log(' hello world') } }
3-js 种实现继承的方式
原型链继承
核心: 将父类的实例作为子类的原型
特点:
- 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
- 父类新增原型方法/原型属性,子类都能访问到
- 简单,易于实现
构造继承
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
特点:
- 解决了1中,子类实例共享父类引用属性的问题
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承(call多个父类对象)
实例继承
核心:为父类实例添加新特性,作为子类实例返回
特点:
- 不限制调用方式,不管是
new 子类()
还是子类()
,返回的对象具有相同的效果
- 不限制调用方式,不管是
拷贝继承
特点:
- 支持多继承
组合继承
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
特点:
- 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
- 既是子类的实例,也是父类的实例
- 不存在引用属性共享问题
- 可传参
- 函数可复用
4-什么是闭包?有什么作用?
闭包是指有权访问另外一个函数作用域中的变量的函数。可以理解为(能够读取另一个函数作用域的变量的函数)
闭包避免了使用全局变量,此外,闭包允许将函数与其所操作的某些数据(环境)关连起来。这一点与面向对象编程是非常类似的,在面对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
5-什么是预解析?
JS代码在执行之前,会对代码进行预解析,寻找作用域中的var 和function ,然后对其进行事先声明,在从上到下执行代码。这就是一个预解析的过程。
在下面这行代码中,JS从左向右进行了预解析处理,先运算 a.x = {n: 2},在运算 a = {n: 2}。
a.x = {n: 2}解析时候,由于a没有x这个属性,所以在堆内存中会开辟一块地址,专门设置x的属性.
运算 a = {n: 2},将a重新赋值,在堆中开辟了一块新的地址内存,此时a的地址指向了 {n: 2},
然后a与 {n: 1}切断关联,但是b的地址还是指向了原来的{n: 1},但是由于x的属性没有赋值,所以返回underfined。
JS预解析的过程可以这样理解:
预解析就像是一场游戏,游戏开始之前先清点玩家参与的名单,只要你开黑加入了这场团战,那你就是游戏的参与者。无论你挂机还是不挂机,都是游戏的参与者。
underfined就好比挂机的。
报错找不到的就不是这场游戏的参与者。