一些关于JS的基础知识巩固复习、整理
学了忘 忘了学。。。
一 instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
1 | arr = [1,2,3] |
2 | arr instanceof Array |
3 | // true 因为 arr.__proto__ === Array.prototype |
4 | arr instanceof Object |
5 | // true 因为 arr.__proto__.__proto__ === Object.prototype |
一般情况下instanceof 不能判断基本类型
1 | 'abc' instanceof String // false |
2 | 123 instanceof Number // false |
3 | true instanceof Boolean // false |
自己实现 instanceof
1 | const myInstanceof = function(instance, constructor){ |
2 | // 如果是基本类型就返回false 用 typeof 判断 |
3 | if(typeof instance !== 'object' && typeof instance !== 'function' || instance === null){ |
4 | return false |
5 | } |
6 | |
7 | let proto = instance.__proto__ |
8 | // 或者 proto = Object.getPrototypeOf(instance) |
9 | |
10 | while(proto !== null){ // 因为原型链的终点是 null |
11 | if(proto === constructor.prototype) return true |
12 | proto = proto.__proto__ |
13 | } |
14 | return false |
15 | |
16 | // 或者直接用isPrototypeOf判断 |
17 | // return constructor.prototype.isPrototypeOf(instance) |
18 | } |
测试一下
1 | myInstanceof(123,Object) // false |
2 | myInstanceof('abc',String) // false |
3 | myInstanceof([],Array) // true |
4 | myInstanceof([],Object) // true |
5 | myInstanceof({},Array) // false |
6 | myInstanceof({},Object) // true |
7 | myInstanceof(Math.max,Function) // true |
二 call bind apply的区别
这三个方法都是在函数的原型链上的方法,作用是用来改变this指向
这三个函数的第一个参数都是指定this
call方法
1 | // 通过数组的方法将类数组转为数组avascript |
2 | let arr3 = {0:1,1:0,2:3,3:2,length:4} |
3 | Array.prototype.slice.call(arr3) // 这样arr3本来没有slice方法 现在也可以使用了 |
apply方法
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
appyl与call的区别
- call的第二个参数传的是参数列表
- apply的第二个参数传的的数组
1 | // 求最大值 |
2 | Math.max(1,3,4,2) // 4 |
3 | Math.max.call(null,1,3,2,4) |
4 | Math.max.apply(null,[1,3,2,4]) // 这样可以直接求数组中的最大值 |
bind方法
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
bind改变this指向后不会立即调用 而是返回一个yongq8
1 | let obj = { |
2 | say(){ |
3 | console.log(this) |
4 | } |
5 | } |
6 | setTimeout(obj.say,1000) // 调用的时候打印的this是window,1000) |
7 | // 我们可以通过bind绑定this |
8 | setTimeout(obj.say.bind(obj),2000) // 打印的时候是obj |
9 | |
10 | const fn = function(){ |
11 | console.log(this.name) |
12 | } |
13 | let obj = { |
14 | name: 'obj 的name' |
15 | } |
16 | let objFn = fn.bind(obj) |
17 | objFn() // 'obj'的name |
三 Object.defineProperty
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
对象数据属性默认有四个特性
- value 值 默认为undefined
- configurable (是否可修改描述符对象 是否能通过delete删除属性 默认为false)
- enumerable (是否可被遍历 默认为false)
- writable (是否可改变 默认为false)
对象访问器属性 不包含数据值 有四个特性:
- Configurable
- Enumerable
- Get
- Set
要修改属性的默认特性,必须使用Object.defineProperty()方法 接受三个参数: 属性所在的对象 属性的名字 一个描述符对象
1 | const object = {}; |
2 | |
3 | Object.defineProperty(object, 'property1', { |
4 | value: 42, |
5 | writable: false, // 值不可变 |
6 | configurable: true, // 可以被修改 可以被delete |
7 | enumerable: false |
8 | }) |
9 | |
10 | object.property1 = 77 // throws an error in strict mode |
11 | console.log(object.property1) // 42 因为该属性的值是不可改变的 |
12 | |
13 | Object.defineProperty(object, 'property1', { |
14 | value: 42, |
15 | writable: true, // 重新修改为值可变 |
16 | }) |
17 | |
18 | object.property1 = 77 |
19 | console.log(object.property1) // 77 现在值是可变的 |
20 | |
21 | delete object.property1 // true 可以被删除 |
22 | |
23 | Object.defineProperty(object,'property2',{ |
24 | value: 55, |
25 | enumerable: true |
26 | }) |
27 | |
28 | // 可被遍历的属性 |
29 | Object.keys(object) // ['property2'] 因为property2的enumerable是true |
30 | for(let key in object) { |
31 | console.log(key) // 'property2' 只有一个属性可被遍历到 |
32 | } |
33 | |
34 | Object.property2 = 77 // throws an error in strict mode |
35 | console.log(Object.property2) // 55 默认就是不可变的 |
36 | |
37 | Object.defineProperty(object,'property2',{ |
38 | writable: true |
39 | }) // 报错 因为 configurable 默认为false 不可再重新定义描述符对象 |
40 | |
41 | delete object.property2 // false configurable 默认为false 属性不可被删除 |
定义访问器属性
1 | var book = { |
2 | _year: 2004, |
3 | edition: 1 |
4 | } |
5 | |
6 | Object.defineProperty(book,'year',{ |
7 | get: function(){ |
8 | return this._year |
9 | }, |
10 | set: function(newValue){ |
11 | if(newValue){ |
12 | this._year = newValue |
13 | this.edition += newValue - 2004 |
14 | } |
15 | } |
16 | }) |
17 | // {_year: 2004, edition: 1} |
18 | book.year = 2005 // 2005 |
19 | book.edition // 2 |
定义多个属性时可以用 Object.defineProperties方法
1 | var obj = {}; |
2 | Object.defineProperties(obj, { |
3 | 'property1': { |
4 | value: true, |
5 | writable: true |
6 | }, |
7 | 'property2': { |
8 | value: 'Hello', |
9 | writable: false |
10 | } |
11 | // etc. etc. |
12 | }) |
四 Object.getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor()方法可以读取属性的描述符
1 | Object.getOwnPropertyDescriptor(object,'property1') |

同理 Object.getOwnPropertyDescriptors()方法用来获取一个对象的所有自身属性的描述符
