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");
打印结果:
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);
打印结果:
arguments.callee
:代表当前函数对象本身
let fun = function () {
console.log(arguments.callee);
}
fun();
打印结果:
案例:计算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__
凭什么子类对象可以访问到父类的属性和父类的方法,以及子类的属性和子类的方法?
子类对象可以直接访问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。
为什么实例对象可以访问到所有的属性和方法?
实例对象可以直接访问自己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只是产生了一个新的函数对象