21. 原型对象和原型链

arguments:

arguments.length为函数实参个数,arguments.callee引用函数自身

函数体内的内置对象,作用域在函数体内

作用:

1. 打印实参伪数组(智能访问元素和length属性,其他的API不能使用)

 function fun(){
   console.log(arguments);
     for(let i=0; i<arguments.length;i++){
         console.log(arguments[i]);
       }
    }

  fun(1,"heihei");

打印结果:

image-20221206141147145

2. 设计不定参函数

   function fun() {
        for (let i = 0; i < arguments.length; i++) {
            if (typeof arguments[i] == "number") {
                console.log("执行数字操作");
            } else if (typeof arguments[i] == "string") {
                console.log("执行字符串操作");
            } else if (typeof arguments[i] == "boolean") {
                console.log("执行布尔操作");
            }
        }
    }

    fun("heihei", 1, true);

打印结果:

image-20221206141905824

arguments.callee:代表当前函数对象本身

let fun = function () {
        console.log(arguments.callee);
    }

    fun();

打印结果:

image-20221206142019303

案例:计算10的阶乘

function adfasfd(n) {
        let c;

        if (n == 1) {
            c = 1;
        } else {
            c = arguments.callee(n - 1) * n;
        }

        return c;
    }

    console.log(adfasfd(10));
    
    打印结果:3628800

原型对象 (函数对象(特指构造函数)的一个属性,prototype)

它保存着所有实例对象共享的属性和方法

所有的行为都是整个类族共享的,不应该属于某一个实例对象

也就是说,没有必要在每个实例创建时,都为这些函数开辟空间

当一个实例对象修改了同名的原型对象属性时,是不能实现功能的,它等价于为自己的实例对象添加了一个新属性

constructor 构造函数

对象原型(_proto_)和构造函数( prototype ) 原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,因为它指回构造函数本身。

对象原型__proto__

image-20221207211146927

image-20221207212413232

凭什么子类对象可以访问到父类的属性和父类的方法,以及子类的属性和子类的方法?

子类对象可以直接访问new出来空间的属性,

子类对象通过__proto__,可以访问子类原型对象上的属性和方法,

通过子类的原型对象prototype指向了父类的实例对象,所有可以访问父类实例对象new出来的属性,

通过父类实例对象的__proto__,访问父类的原型对象的属性和方法

特点:向上找

原型链

是什么?作用?

每一个对象,都有一个原型对象与之关联,这个原型对象它也是一个普通对象,这个普通对象也有自己的原型对象,这样层层递进,就形成了一个链条,这个链条就是原型链.通过原型链可以实现JS的继承,把父类的原型对象赋值给子类的原型,这样子类实例就可以访问父类原型上的方法了。

function Fn() {}// Fn为构造函数
var f1 = new Fn();//f1是Fn构造函数创建出来的对象
构造函数的prototype属性值就是对象原型。(Fn.prototype就是对象的原型)
构造函数的prototype属性值的类型就是对象 typeof Fn.prototype===object.
对象原型中的constructor属性指向构造函数 (Fn.prototype.constructor===Fn)
对象的__proto__属性值就是对象的原型。(f1.__proto__就是对象原型)
Fn.prototype===f1.__proto__ 其实它们两个就是同一个对象---对象的原型。
所有Fn.prototype.__proto__===Object.prototype
typeof Object.prototype ===object。
Object.prototype.__proto__===null。

img

为什么实例对象可以访问到所有的属性和方法?

实例对象可以直接访问自己new出空间的属性,

每个实例对象都有一个__proto__的属性,

它指向类的原型对象,所以可以访问原型对象中的属性和方法

案例:为官方类添加原型对象


//最大数
Array.prototype.max = function(){
        let maxNum = this[0];

        this.forEach((x)=>{
            if(maxNum < x){
                maxNum = x;
            }
        });

        return maxNum;
    }

    let arr = [1,2,3,4,5,6,7,8,9];

    let x = arr.max();

    console.log(x);

apply和call

apply和call:都是函数对象的方法

作用:

1.修改this指向

  • ​ 函数对象.apply(被修改的this指向,[原函数的参数1,参数2...])

  • ​ 函数对象.call(被修改的this指向,原函数的参数1,参数2...)

2.实现了类和函数的解耦

案例 function Dog(name){ this.name = name; } function Cat(name){ this.name = name; } function eat(food1,food2){ console.log(this.name + ":" + food1 + "," + food2); } let d = new Dog("旺财"); eat.apply(d,["火腿肠","狗粮"]); eat.call(d,"骨头","炒细面"); let c = new Cat("哆啦A梦"); eat.apply(c,["老鼠","铜锣烧"]); eat.call(c,"猫粮","披萨");

面试题:apply,call,bind的异同?

1.都是用来修改函数的this指向

2.apply和call用来修饰有名函数,bind用来修饰匿名函数

3.apply的第二个参数必须是数组,bind和call用逗号分开

4.apply和call会直接调用该方法, 而bind只是产生了一个新的函数对象

posted @ 2022-12-10 09:34  千帆qf  阅读(31)  评论(0)    收藏  举报