javascript高级知识点总结


一、构造函数

1.为什么要有构造函数

一些对象具有相同的属性和方法(特征和行为),将他们抽象出一个同一个类型,在JS中就需要通过一个构造函数来创建这些对象,在构造函数内部设置对象的属性和方法

好处:一次封装,多次调用,可省略一些代码,也让代码更具有可读性。

2.获取对象上的属性和方法

(1). 属性:
  a. 实例.属性名;
  b. 实例[“属性名”];
(2).方法:
  a. 实例.方法名;
  b. 实例[“方法名”];

3.设置对象上的属性和方法

(1). 属性:
  a. 实例.属性名=新的值;
  b. 实例[“属性名”]=新的值;
(2). 方法:
  a. 实例.方法名=新的值;
  b. 实例[“方法名”]=新的值;

4.删除原型对象中的say方法

delete

5.构造函数和普通函数

构造函数和普通函数只在调用方式不同

(1). 当成普通函数来调用
    a. 函数内部的this指向调用的对象(如果没有找到调用的对象,this指向window)
    b. 函数的返回值由return语句决定,如果没有说明函数没有返回值(返回值是undefined)

(2). 当成了构造函数来调用会经历以下过程
    a. 创建一个该构造函数的实例
    b. 将构造函数内部的this的值指向该实例
    c. 执行函数体
    d. 默认的返回值:该实例

(3). 函数调用的4种方式 function fn(){}
    a. 普通调用:fn();
    b. 当成构造函数调用:new fn();
    c. 被对象调用:o.fn();
    d. 上下文模式:call/apply

(4). 构造函数的返回值
    a. 构造函数没有手动添加返回值,返回构造函数的实例
    b. 构造函数返回基本数据类型的值,返回的还是构造函数的实例
    c. 构造函数返回对象类型的值,返回就是那个对象

二、原型对象

1.什么是原型对象?
构造函数的prototype属性:随着实例化的次数增加,不同的对象他们拥有的say方法指向不同的内存,功能相同,造成了内存的浪费,为了解决内存,将这个方法放在某个对象(原型对象)中.

结论1:给构造函数的prototype属性(对象)添加一个方法,这个方法就可以被构造函数的实例所共享
    推论1:构造函数的prototype属性(对象)上面的属性、方法都可以被构造函数的实例所共享
    推论2:Student.prototype.constructor===s1.constructor

结论2:构造函数的实例有一个__proto__指向的是构造函数的prototype属性(原型对象) s1.proto===Student.prototype

总结:
    a. 原型对象是构造函数的prototype属性
    b. 构造函数的实例的__proto__属性指向原型对象
    c. 原型对象有一个constructor属性指向构造函数本身
在这里插入图片描述

三、对象的属性的读取与设置

查找一个对象上的是否存在某个属性的过程

a. 查找当前对象(s1)的内存中是否定义了该属性,找到就停止查找
b. 去当前对象的__proto__属性(原型对象)中去查找是否定义了该属性,找到就停止查找
c. 如果2中没找到,就去原型对象的原型对象中去查找是否定义了该属性 s1.proto.proto
n. 找到某个对象(是没有原型对象的:没有__proto__属性),如果这个对象中还没有,确定了无法获取该属性

四、继承

1.继承的概念

a继承自b——> a.proto===b

2. 扩展原型对象实现继承

构造函数有一个prototype属性(原型对象),通过给原型对象添加一个属性、方法,从而可以让构造函数的实例可以访问到,这种继承模型称之为:扩展原型对象实现继承。

function Person(){};
Person.prototype.age = 20;
var p1 = new Person();

由于p1是Perosn的实例,所以p1是继承自Person构造函数的原型对象。

3.替换原型对象实现继承

为什么要用替换原型对象实现继承?
  当我们需要给构造函数的原型对象中添加很多个属性、方法的时候,如果一直使用扩展原型对象,多写很多冗余(重复)的代码

如何实现替换原型对象实现继承?
  重新给构造函数的prototype属性赋值,值是一个全新的对象,在这个对象中添加属性、方法;要注意一定要给这个对象添加constructor属性,值指向构造函数本身

4.混入继承

混入继承的使用场景:已知对象o,o2,需要将o中的功能(属性、方法)拷贝到o2中 jQuery.extend() 方法;

for (var key in o) {//key是o的属性名称,key是字符串类型的值
    //属性的值:
    var value=o[key];
    //设置o2中的同名属性
    o2[key]=value;
}

将混入继承的模型封装成函数

/**
 * 混入继承:将源对象中的属性和方法拷贝到目标对象中
 * @param target 目标对象:接收数据的对象
 * @param source 源对象:数据从哪个对象来
 */
function mixin(target,source){
   for (var key in source) {
         var value=source[key];
         target[key]=value;
         //相当于:
         //target[key]=source[key];
       }
   return target;
}

jQuery中的$.extend()实现原理就是混入继承

5.原型+混入继承

function Cat(){}
    Cat.prototype.extend=function(source){
        //调用实现混入继承的函数往原型对象中添加属性、方法
        mixin(Cat.prototype,source);
};

原型+混入继承在jQuery中也有很常见的应用:$.fn.extend()–>jQuery.prototype.extend()

6.经典继承

实现的功能:已知一个对象o,需要创建一个新的对象(o2),这个新的对象继承自对象o
经典继承的使用场景:要创建一个对象(不需要关心构造函数)新对象需要继承自另一个指定的对象

//o2.__proto__===o; 将经典继承封装成一个函数:
function create(o){
    function F(){}
    F.prototype=o;
    return new F();//返回的就是F的实例    
}

ES5(IE9以下版本不支持):Object.create()的实现原理就是源自于经典继承

在旧的浏览器中应用经典继承

//1、首先应该先检测浏览器是否支持Object.create()
    if(typeof Object.create !=="function"){
        Object.create=function(o){
            function F(){}//一个任意的构造函数
            F.prototype=o;//设置构造函数的原型对象
            return new F();//返回的就是F的实例
        };
    }

五、原型链

1.原型链的基本概念

JS由对象组成,一个对象就有它的原型对象(proto),原型对象也有它的原型对象,一直到原型链的顶端,这样构成了一个具有链条形状的结构,称之为原型链
__proto__该属性可以被修改,但是无法被删除

下面是对象字面量的原型链图
在这里插入图片描述

下面是构造函数创建对象的原型链图
在这里插入图片描述
下面是数组对象的原型链图
在这里插入图片描述

一般来说,无论是对象字面量,还是构造函数创建的对象、内置对象,基本包装了类型的对象,2次原型查找(.proto)就可以找到

六、属性方法

1. Object.prototype.toString()

var obj={};
    console.log(obj.toString());//"[object Object]"
    console.log(Object.prototype.toString.call([]));//"[object Array]"
    console.log(Object.prototype.toString.call(/abc/));//"[object RegExp]"
    console.log(Object.prototype.toString.call(new Date()));//"[object Date]"
    console.log(Object.prototype.toString.call(1));//"[object Number]"
    //1-->转换为基本包装类型的对象
    console.log(Object.prototype.toString.call("abc"));//"[object String]"
    console.log(Object.prototype.toString.call(true));//"[object Boolean]"
    console.log(Object.prototype.toString.call(function(){}));//"[object Function]"
    function Cup(){}
    var cup=new Cup();
    console.log(Object.prototype.toString.call(cup));//"[object Object]"

使用Object.prototype.toString.call()只能检测内置对象的类型——>$.type

2. Object.prototype.hasOwnProperty()

用来判断方法的参数(字符串类型)是否是对象的自有属性(属性定义在对象自身的内存中——>通过原型链找到的属性就不对了)

3. Object.prototype.isPrototypeOf()

表示当前对象是否是参数的原型对象(或在参数的原型链上)

4. Object.prototype.propertyIsEnumerable()

表示参数(字符串类型)是否是当前对象的可枚举(for…in遍历)属性

5. Object.defineProperty(); //ES5诞生的

//参数1:需要定义属性的对象
    //参数2:属性的名称(字符串类型)
    //参数3:属性的描述符(对象)
    value;
    enumerable; //添加了一个不可枚举属性
    writable;  //添加一个不可使用赋值运算符的属性
    configurable;  //值为true表示该属性可以被删除,值为false表示该属性不可被删除
    get;  //定义一个只读(只能获取值)属性
    set;  // 定义一个只写属性,仅仅设置set
Object.defineProperty(o1,"length",{
         enumerable:false,
         value:"170"
});

6. a instanceof b

表示a是否为b(函数)的实例

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值