1.css父级元素margin-top:20px;子元素margin-top:10px;最后显示结果margin值是多少?
原因就是子元素和父元素上边框重合在一起
- 解决办法:
- 为父元素设置内边距padding。来代替给子元素设置margin-top
- 为父元素设置边框border。
- 为父元素设置 overflow: hidden
2.JS中的数据类型
- 基本类型:
- number,string,boolean,null,undefined,symbol。基础类型存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量
- 引用类型数据:
- object(function,array,Date…),引用类型存储在堆内存,存储的是地址,多个引用指向同一个地址
3.如何判断变量的类型
1.typeof
对于基础类型是可以检测到的,除了null返回是object
2.instance of
可以正确的判断数据类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的prototype
3.最好的方法是使用Object.prototype.toString
方法,可以检测任何数据类型,返回的结果是 [object type]的形式
// 封装检测类型的函数
function detectType(type){
return function(obj){
return {
}.toString.call(obj) === `[object ${
type}]`
}
}
//根据自己的需求扩展 这里我展示数组和字符串,记住类型的首字母大写
const isArray = detectType('Array')
//const isString = detecType('String')
console.log(isArray([1,2,3])); // true
console.log(isArray('[1,2,3]')); // false
4.关于this的指向问题
1.在构造函数中,this指的是new出来的对象
function Person(name,age){
this.name = name
this.age = age
console.log(this)
console.log(this.__proto__.constructor)
}
var ldh = new Person('ldh',10)
var zxy = new Person('zxy',20)
2.原型对象函数里面的this指向的是实例对象(即:这个方法的调用者)
Array.prototype.pt = function() {
console.log(this,111)
}
var a = [1,2,3,4]
a.pt()
3.普通函数this指向window
function dog(){
var user = '二狗子'
console.log(this.uesr) // undefined
console.log(this) // window
}
4.绑定事件函数,this指向函数的调用者(btn按钮事件)
var btn = document.getElementById('btn')
btn.onclick = function () {
console.log(this);
}
5.定时器函数,this指向的是window
6.对象的方法,this指向的事对象本身
var obj = {
name:'zs',
say:function(){
console.log('my name is'+ this.name)
}
}
// 输出的是 my name is zs
7.匿名函数的this指向window,匿名函数的执行环境具有全局性,因此其this指向一般是window
var name = 'the window'
var obj = {
name = 'my window',
getName:function(){
console.log(this,'this') //这里的this指向obj
return function(){
return this.name
}
}
}
console.log(obj.getName()()) // the window
/*
如果想改变this的指向 指向'my window'的话可以把this对象赋值给that的变量
*/
5.什么是闭包函数?(关于闭包的一些使用场景)
// 详细链接 https://zhuanlan.zhihu.com/p/87950150
// 闭包函数 内部函数可以访问外部函数中的变量
// 作用:延长了变量的作用范围
// 产生的原因:函数在执行的时候遇到一个变量,他会先看看自己的作用域里有没有该变量,没有的话就会向上从父级作用域里去查找,直到找到位置,否则报错undefined
// 缺点:由于闭包会携带包含它的函数作用域,因此会比其他函数占用更多的内存
function f1(){
var a = 1;
function f2(){
console.log(a)
}
return f2
}
f1() // 1
6.请快速答出此题的答案并解释:var x, y = 1; x + y = ?
/*
var x 没有赋值,初始值是undefined
y = 1
两个变量相加等于NAN
根据运算符的隐式转换规则:
若任何一侧是 string 或 object 则两边转换为 string 进行连接
否则均转换为 number 并进行相加
undefined 只与字符串进行累加时有效(undefined 视为字符串"undefined"处理),其他情况皆返回 NaN
*/
7.说一下对原型和原型链的理解
每个函数在创建的时候都会生成一个
prototype
属性,这个属性是个对象(原型对象),原型对象有个属性constructor
属性,这个属性指向构造函数本身
实例和构造函数的关系
每次调用构造函数创建一个实例,这个实例的
[ [Prototype] ]
属性就会赋值为构造函数的原型对象。脚本中没有访问[ [Prototype] ]
属性的标准方式,会在对象身上暴露出一个__proto__
属性,通过这个可以访问对象的原型
函数中的原型对象通过prototype来访问,实例对象通过__proto__来访问
function Person( name ){
}
let p1 = new Person()
console.log( Person )
console.log( Person.prototype ) // Object
console.log( p1.__proto__ ) // Object
原型链:在读取原型身上的方法或属性时,首先会从实例自身去搜索,如果没有,则会继续搜索实例的原型,直至为null,null没有原型
// 构造函数
function Foo(name, age) {
this.name = name;
this.age = age;
}
Object.prototype.toString = function () {
//this是什么要看执行的时候谁调用了这个函数。
console.log("I'm " + this.name + " And I'm " + this.age);
}
var fn = new Foo('小明', 19);
fn.toString(); //I'm 小明 And I'm 19
console.log(fn.toString === Foo.prototype.__proto__.toString); //true
console.log(fn.__proto__ === Foo.prototype)//true
console.log(Foo.prototype.__proto__ === Object.prototype)//true
console.log(Object.prototype.__proto__ === null)//true
当fn调用
toString()
方法时,fn发现自身没有这个方法,就会去Foo.prototype
中去找,发现还是没有,就会去Object.prototype中去找。就会调用Object.prototype.toString()
方法
8.有没有遇到内存泄露的情况,怎么处理
- 原文连接:https://blog.csdn.net/weixin_34249678/article/details/91470852
- 什么是内存泄漏 是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费。而对于一个持续使用的网页端来说,如果一些不能用到的内存没有被及时释放,这就叫内存泄漏。但是我们都知道,我们网页端的承载量是有限的,不断的往一个气球里面不断吹气,气球总有吹爆的一刻。浏览器的表现就是浏览器崩溃
1. 最常见的泄漏点就是闭包。内部函数引用外部函数的变量,得不到释放
2. js的垃圾回收机制 js中的内存回收机制采用的是 引用计数:垃圾回收器会定期扫描内存,当某个内存中的值被引用为零时就会将其回收。当前变量已经使用完毕但依然被引用,导致垃圾回收器无法回收这就造成了内存泄漏。
3. 意外的全局变量。函数中的变量没有声明,直接赋值。
4. 定时器,定时器不清除,一直占用内存得不到释放。
5. 不清理dom元素的引用。
6. 监听事件的解除。
9.js 设计模式(重点 这个经常被问到)
- 发布订阅模式
- 发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。
function Public() {
this.handlers = {
};
}
Public.prototype = {
// 订阅事件
on(eventType, handler) {
if(!(this.handlers.hasOwnProperty(eventType))) {
this.handlers[eventType] = [];
}
this.handlers[eventType].push(handler);
return this;
},
// 触发事件(发布事件)
emit(eventType) {
let handlerArgs = Array.prototype.slice.call(arguments,1);
for(let i = 0; i < this.handlers[eventType].length; i++) {
this.handlers[eventType][i].apply(this,handlerArgs);
}
return this;
},
// 删除订阅事件
off(eventType, handler) {
let currentEvent = this.handlers[eventType];
let len = 0;
if (currentEvent) {
len = currentEvent.length;
for (let i = len - 1; i >= 0; i--){
if (currentEvent[i] === handler){
currentEvent.splice(i, 1);
}
}
}
return this;
}
};
let Publisher = new Public();
//订阅事件a
Publisher.on('a', function(data){
console.log(1 + data);
});
Publisher.on('a', function(data){
console.log(2 + data);
});
//触发事件a
Publisher.emit('a', '我是第1次调用的参数').emit('a', '我是第2次调用的参数');
// Publisher.emit('a', '我是第2次调用的参数');
// 1我是第1次调用的参数
// 2我是第1次调用的参数
// 1我是第2次调用的参数
// 2我是第2次调用的参数
10.src和href的区别
1. href:Hypertext Reference的缩写,超文本引用,它指向一些网络资源,建立和当前元素或者说是本文档的链接关系。在加载它的时候,不会停止对当前文档的处理,浏览器会继续往下走。常用在a、link等标签。
<a href="http://www.baidu.com"></a>
<link type="text/css" rel="stylesheet" href="common.css">
// 如上面所显示的那样,当浏览器加载到link标签时,会识别这是CSS文档,就会并行下载该CSS文档,但并不会停止对当前页面后续内容的加载。这也是不建议使用@import加载CSS的原因。
2. src:source的所写,表示的是对资源的引用,它指向的内容会嵌入到当前标签所在的位置。由于src的内容是页面必不可少的一部分,因此浏览器在解析src时会停下来对后续文档的处理,直到src的内容加载完毕。常用在script、img、iframe标签中,我们建议js文件放在HTML文档的最后面。如果js文件放在了head标签中,可以使用window.onload实现js的最后加载。
<img src="img/girl.jpg">
<frame src="top.html">
<iframe src="top.html">
<script src="show.js"><