1. JS原型链
-
一个对象除了有自己定义的属性,还有一个属性“_proto_”(它是一个对象),"obj._proto_"里也有很多属性,包括valueOf、 toString、 constructor等……
图片.png -
“obj._proto_”其实也有一个叫_proto_的属性(但是一般值为null)
-
obj之所以可以拥有valueOf、 toString、 constructor这几个属性,是跟“._proto_”有关:
当我们「读取」 obj.toString 时,JS 引擎会做下面的事情:
1. 看看 obj 对象本身有没有 toString 属性。没有就走到下一步。
2. 看看 obj.__proto__ 对象有没有 toString 属性,发现 obj.__proto__ 有 toString 属性,于是找到了
所以 obj.toString 实际上就是第 2 步中找到的 obj.__proto__.toString。
可以想象,
3. 如果 obj.__proto__ 没有,那么浏览器会继续查看 obj.__proto__.__proto__
4. 如果 obj.__proto__.__proto__ 也没有,那么浏览器会继续查看 obj.__proto__.__proto__.proto__
5. 直到找到 toString 或者 __proto__ 为 null。
上面的过程,就是「读」属性的「搜索过程」。
而这个「搜索过程」,是连着由 __proto__ 组成的链子一直走的。
这个链子,就叫做「原型链」。
## **共享原型链**
现在我们有另一个对象
var obj2 = { name: 'obj2' }
如图:
image那么 obj.toString 和 obj2.toString 其实是同一个东西,也就是 obj2.proto.toString。
这有什么意义呢?
如果我们改写 obj2.proto.toString,那么 obj.toString 其实也会变!
这样 obj 和 obj2 就是具有某些相同行为的对象,这就是意义所在。
差异化
如果我们想让 obj.toString 和 obj2.toString 的行为不同怎么做呢?
直接赋值就好了:
obj.toString = function(){ return '新的 toString 方法' }
image
总结:
「读」属性时会<u style="border-bottom-color: grey; border-bottom-style: dashed; border-bottom-width: 1px; text-decoration: none;">沿着原型链搜索</u>。
2. 利用filter结合indexOf,可以巧妙地去除Array的重复元素:
deleteRepElements() {
var newPhotos, oldPhotos = ['x1', 'x2', 'x3', 'x2', 'x3', 'x4'];
newPhotos = oldPhotos.filter(function (element, index, self) {
return self.indexOf(element) === index;
});
console.log(newPhotos)
}
其中: element, index, self是filter里callback的三个输入参数,固定参数(不能该名字),默认代表:
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
参数:
- callback
用于测试数组的每个元素,返回true保留元素,否则返回false。
它接受三个参数:- element
数组中正在处理的当前元素。 - index
数组中正在处理的当前元素的索引。 - array
召唤出滤波器的这个数组。
- element
- thisArg
执行回调时用作此值的值。
3. 给 Array 对象添加新的方法/函数:以后任何一个数组都会拥有这个新函数
Array.prototype.duplicator = function() {
let s = this.concat(this)
return s
}
let t = [1,2,3,4,5].duplicator()
console.log(t) // [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
4. apply方法和call方法:
- apply方法:是将其他对象里的属性/方法添加到自己对象里
如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:
blackCat.say.call(whiteDog);
//这就是将blackCat对象的say方法添加whiteDog对象里。从此我们的whiteDog就有say方法了。
所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
这样domNodes就可以应用Array下的所有方法了。
5. JS合并两个数组的方法
var array = ["football", "basketball"];
var array2 = ["volleyball", "golfball"];
var i = Array.prototype.push.apply(array,array2);
console.log(array); // ["football", "basketball", "volleyball", "golfball"]
console.log(i); // 4
网友评论