重新认识函数对象

函数对象

function foo(a, b) {
	return a * b
}

1. length属性

foo.length
// 2

参数个数为2

2. constructor属性

foo.constructor) 
// [Function: Function]

constructor属性,引用的是Function()这个构造器函数

3.arguments对象

function f() {
	return arguments
}
f(1, 2, 3) // [1, 2, 3]

arguments 是类数组对象,包含了索引元素和length属性,但是不提供sort()、slice()这样的方法
可以将类数组转化为数组

function f() {
	return [].slice.call(arguments)
}

4. call 和 apply方法

这两个方法用来触发函数,并制定相关的调用参数。最重要的功能,是它可以让一个对象去"借用"另一个对象的方法

const obj = {
	name: 'Ninja',
	say (who) {
		return `${who} say I'm ${this.name} `
	}
}
obj.say('Jack')
// Jack say I'm Ninja 

const my = {name: ‘runner’}

obj.say.call(my, 'Lee')
// Lee say I'm runner 

当call被调用时,其中的this,就被自动设置成了my对象的引用,this.name返回的不再是"Ninja",而是"runner"了。
如果没有指定call的第一个参数,或者传入null,它的调用对象会被默认为全局对象

call()传入参数,是一次传入
obj.say.call(my, 'a', 'b', 'c')

apply() 传入参数是以数组的形式
obj.say.apply(my, ['a', 'b', 'c'])

5. prototype属性

typeof foo.prototype
// object
function Person(name, age) {
	this.name = name
	this.age = age
	this.say = function() {
		return `I'm ${this.name}, ${this.age}`
	}
}
5.1 通过prototype添加属性和方法
Person.prototype.place = 'china'
Person.prototype.getInfo = function() {
	return `I'm come from ${this.place}`
}

const bob = new Person('bob', 18)

bob.say()
// I'm bob, 18

bob.getInfo()
// I'm come from china

对于原型来说,它具有"实时"性。js中对象都是通过引用传递,因此我们创建的所有实体中并没有一份属于自己的原型副本。
这意味着我们随时可以修改prototype属性,并且由同一个构造器创建的所有对象的prototype属性也都会同时改变

5.2当向原型添加新方法
Person.prototype.get = function(what) {
	return this[what]
}

bob对象在新方法定义之前就被创建,但是依然可以在该对象中访问新增的方法

bob.get('place')
5.3 自身属性与原型属性

getInfo() 方法中用this指针访问对象,也可以用Person.prototype

Person.prototype.getInfo = function() {
	return `I'm come from ${Person.prototype.place}`
}

bob.place访问实例的属性时,在bob对象上找不到place,就会去构造器的原型bob.constructor.prototype上查找。

bob.constructor === Person
bob.constructor.prototype.place === bob.place
5.4 利用自身属性重写原型属性
Person.prototype.name = 'mirror'
bob.name = 'dog'
bob.name
// 'dog'
bob.hasOwnProperty('name'))
// true
delete bob.name
bob.name
// 'mirror'
bob.hasOwnProperty('name')
// false

hasOwnProperty属性可以判断原型属性到底是原型链中哪个原型的属性

bob.toString()
// [object Object]
bob.hasOwnProperty('toString')
// false
bob.constructor.hasOwnProperty('toString')
// false
bob.constructor.prototype.hasOwnProperty('toString')
// false
Object.hasOwnProperty('toString')
// false
Object.prototype.hasOwnProperty('toString')
// true
5.5 枚举

使用for-in枚举对象的属性

    1. 不是所有的属性都可以被枚举,length、constructor属性就不会被显示。判断属性是否可以被枚举,可以用propertyIsEnumerable()方法来判断
    1. 原型链中的属性也会被显示出来,前提是可以被枚举。可以使用hasOwnProperty判断是自身属性还是原型属性
    1. 对于原型属性,propertyIsEnumerable()都会返回false
for(let prop in bob) {
	console.log(`${prop} = ${bob[prop]}`)
}

for(let prop in bob) {
	if (bob.hasOwnProperty(prop)) {
		console.log(`${prop} = ${bob[prop]}`)
	}
}
bob.propertyIsEnumerable('place')
// false
5.6 isPrototypeOf()

每个对象都有一个isPrototypeOf()方法,判断当前对象是否是另一个对象的原型

const monkey = {
	hair: true,
	feeds: 'bananas',
	breathes: 'air'
}
function Human(name) {
	this.name = name
}
Human.prototype = monkey

const tom = new Human('tom')

monkey.isPrototypeOf(tom)
// true

在知道monkey可能是tom的原型才使用isPrototypeOf判断
在不知道某个对象原型是什么的情况下,使用Object.getPrototypeOf()方法来判断

Object.getPrototypeOf(tom) === monkey
// true
5.7 __proto__
tom.feeds = 'rice'
tom.feeds
// rice
tom.breathes
// air

breathes 不在tom对象的自身属性中,所以就去原型中查询,有一个__proto__属性链接原型

tom.__proto__ === monkey
// true

__proto__是某个实例对象的属性,prototype是构造器函数的属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值