- 重排重绘
__proto__
和prototype
分别是什么- 哪种情况下
__proto__
和prototype
的指向是同一个? - 原型链原理
- 在原型链上
Object
再往上是什么 new
和Object.create
的区别typeof array null undefined NaN
分别是什么- 把
undefined
和null
转成Number
分别是什么 - 如何判断是否为数组?
instanceof
和constructor
的区别
1. 重排、重绘
- 重排
重排是根据渲染树中每个渲染对象的信息,计算出各个渲染对象的几何信息(即DOM对象的位置和尺寸大小),将各个渲染对象放置在页面的正确位置。
某个DOM节点的几何信息更改,就需要重新计算,然后重新布局。即导致重排。
引发重排的操作:
- 页面的首次渲染
- 浏览器的窗口大小发生改变
DOM
元素位置和尺寸发生改变- 元素的内容发生改变(比如:文字数量或图片大小等)
- 文本元素字体大小发生改变
- 添加或删除可见的
DOM
元素 - 激活
CSS
的伪类(比如::hover
) - 设置
style
属性(width,height,margin,padding,border
等等) - 查询某些属性或调用某些方法(
scrollIntoView(),scrollTo(),scrollIntoView()
等等)
- 重绘
重绘是当页面元素的样式改变且不影响该元素在文档流中的位置就会发生重绘。比如,改变元素的颜色等
常见引起重回的样式属性有:
color
border-style
visibility
background
text-decoration
background-image
background-position
background-repeat
outline-color
outline
outline-style
border-radius
outline-width
box-shadow
background-size
补充:DOM操作是一项高成本的操作,尽量减少重排。
2. __proto__
和prototype
分别是什么
其实可以理解为prototype
是构造函数的属性,__proto__
是实例对象的属性,他们都指向同一个对象
function Person(){
}
let person1 = new Person();
person1.__proto__ === Person.prototype; // true
记住2点就够了
- 每个对象都有一个
__proto__
属性指向它构造函数的prototype
- 每个构造函数都有一个
prototype
原型对象,同样这个原型对象也有一个__proto__
属性。
3. 哪种情况下__proto__
和prototype
的指向是同一个?
Function.__proto__ === Function.prototype; // true
4. 原型链原理(点击查看原型链和继承相关知识)>>
5. 在原型链上Object
再往上是什么
null
Object
的实例,处于原型链的末端,因而它没有原型。
6. new
和Object.create
的区别
new
一个对象发生了什么?
- 创建了并返回一个新的对象
- 对象内
this
指向这个新的对象
function F(){
this.a = 1;
}
const obj = new F()
obj.a; // 1
使用new操作符创建的对象具备原来对象的属性
Object.create
:
- 创建一个新对象
- 语法
Object.create ( proto, [ propertiesObject ] )
参数:
- 第一个参数
proto
是一个对象或者构造函数,作为新对象的原型 - 第二个参数
propertiesObject
(可选),为这个新对象添加属性
function F(){
this.a = 1;
}
const obj = Object.create(F,{
b: {
value: 2
}
});
obj.a; // undefined
obj.b; // 2
可见:Object.create()创建的新对象丢失了原来对象的属性
7. typeof array null undefined NaN
分别是什么
typeof [数组]; // object
typeof null; // object
typeof undefined; // undefined
typeof NaN; //number
8. 把undefined
和null
转成Number
分别是什么
Number(null); // 0
Number(undefined); // NaN
9. 如何判断是否为数组?
- 使用
instanceof
const arr = [1,2,3];
arr instanceof Array; // true
- 使用
constructor
const arr = [1,2,3];
arr.constructor === Array; // true
- 使用
Object.prototype.toString()
方法
const arr = [1,2,3];
Object.prototype.toString.call(arr) === "[object Array]"; // true
- 使用ES6提供的Array.isArray()方法
const arr = [1,2,3];
Array.isArray(arr); // true
10. instanceof
和constructor
的区别
constructor
- 我们创建的每一个函数都有一个
prototype
原型属性,这个属性是一个指针,指向一个对象。默认的情况下,所有的原型对象有一个构造函数constructor
属性,这个属性是一个指向prototype
属性所在函数的指针。 constructor
属性在构造函数的原型里,并且指向构造函数,就可以利用constructor
属性来判断一个实例对象是由哪个构造函数构造出来的,也可以说判断它属于哪个类。- ⚠️当构造函数
Person.prototype
等于一个字面量定义出来的对象时,constructor
属性不再指向这个构造函数Person
(即原型链重写会导致constructor
指向改变或constuctor
不复存在)
instanceof
instanceof
运算符是用来判断某个实例对象是否由某个构造函数构造而来(这点和constructor
的作用相同)- ⚠️ 但是原型链重写并不会影响
instanceof
的判断,因为instanceof
是根据原型链来判断构造函数的,只要对象实例的原型链不发生变化,instanceof
便可以正确判断 instanceof
不仅可以判断实例对象直接的构造函数,而且还能判断原型链上所有的构造函数