文章目录
Js:
一、什么是闭包?(要理解闭包的原理)
闭包就是有权访问其他函数作用域中的变量的函数
1. 闭包的原理:
用我自己的话说:当我们定义一个函数时,需要访问函数内部的变量是访问不到的,所以需要在函数内部定义一个匿名函数并return 出去,这样就可以在函数外部访问了
2. 作用域链
首先,后台的执行环境都有一个表示变量的对象 – 变量对象。全局环境的变量对象始终存在,而函数内部中局部环境的变量对象,则只在函数执行过程中存在
- 在创建函数时,会先创建一个预包含全局变量对象的作用域链(指向变量对象的指针),这个作用域链保存在内部scope属性中
- 调用这个函数时,会为这个函数创建一个执行环境,然后通过复制函数内部scope 属性中的对象构建执行环境的作用域链
- 会在该函数执行环境作用域前端创建一个活动对象(0 活动对象,1 全局对象)
- 在函数内部定义的匿名函数会将外部函数的活动对象添加到他的作用域中
- 当内部函数返回后,内部匿名函数的作用域链被初始化为包含外部函数的活动对象和全局变量对象,这样内部匿名函数就可以访问外部函数的所有变量
注意
外部函数执行完后,活动对象也不会被销毁,因为内部函数的作用域链仍然在引用这个活动对象
当外部函数被返回后,他的作用域链会被销毁,但是他的活动对象依然被保存在内存中,直到内部匿名函数被销毁,外部函数的活动对象才会被销毁。
3. 创建常见闭包的方式
在一个函数内部创建一个匿名函数
function out() {
var num = 1;
return function (n){
return (n + num)
}
}
var a = out()
console.log(a(1))
console.log(out()(2))
4. 闭包中的this指向问题
this 是在运行时基于函数的执行环境绑定的
- 在全局函数中,this等于window
- 当函数被某个对象的方法调用时,this等于那个对象
每个函数在调用时都会自动取得两个特殊变量:this 和 arguments,内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此不可能访问到外部函数的这两个变量
解决办法
把外部函数作用域中的this 对象保存在一个闭包能访问到的变量里,就可以让闭包访问该对象了。
var name="welkin"
var obj = {
name : "zhangsan",
getName: function(){
return function(){
return this.name
}
}
}
console.log(obj.getName()()) //welkin
使用变量储存this:
var name="welkin"
var obj = {
name : "zhangsan",
getName: function(){
var that = this;
return function(){
return that.name
}
}
}
console.log(obj.getName()()) //zhangsan
5. 闭包带来的问题
如果闭包的作用域链中保存着一个HTML元素,则意味着该元素永远无法被销毁(引用计数至少为1),导致内存泄漏
解决办法:
- 将元素副本保存在变量里
- 在变量副本使用完之后,将元素变量设置为null
二、什么是原型链,什么是工厂模式
1. 工厂模式
工厂模式是一种设计模式,这种模式抽象了创建具体对象的过程
工厂模式本质上一种函数,用这个函数以特定的接口来创建对象
//简单写了一下
function creatP(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
alert(this.name)
}
return o;
}
var p1 = creatP('zhangdan',86)
var p2 = creatP('welkin', 18)
可以多次调用这个函数,每次都会返回一个两个属性和一个方法的对象
局限性:
解决了多个相似对象的问题,但是没有解决对象识别问题(即怎样知道一个对象的类型)
因此诞生了构造模式
2. 构造模式
构造函数是为了解决工厂模式无法识别对象的问题,构造函数可以用来创建特定类型的对象
function creatP(name, age) { // 记得要将构造函数首字母大写
this.name = name;
this.age = age;
this.sayName = function () {
alert(this.name)
}
}
var p1 = new creatP('zhangdan', 86)
var p2 = new creatP('welkin', 18)
可以看出和工厂模式创建对象的区别:
- 没有显示的创建对象
-直接将属性和方法赋给了this 对象 - 没有return
使用new 操作符创建构造函数的实例
- 创建一个新对象
- this指向这个对象
- 为这个对象添加属性
- 返回新对象
在上面的代码里,p1和p2 分别保存着Person 的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,且该属性指向Person
使用instanceof操作符进行检测,这个对象既是object 的实例也是person 的实例
创建自定义构造函数的意义
可以将它的实例标识为一种特定的类型(这是构造函数模式胜过工厂模式的地方)
在上边的例子里,p1和p2 之所以同时是object 的实例,是因为所有的对象均继承自object
2. 原型模式
原型属性:创建的每一个函数都有一个prototype 属性,这个属性是一个指针,指向函数的原型对象(需要明确的一点:这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间)
这个对象的用途是:包含可以有特定类型的所有实例共享的属性和方法
原型对象:
- 按照字面意思理解:
使用原型属性(prototype)通过构造函数而创建的对象的实例
使用原型对象的好处:可以让所有对象实例共享他所包含的属性和方法(不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中)
原型对象存在的问题
- 省略了构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值
- 对于引用类型的属性来说,原型中的属性被实例共享,实例没有属于自己的全部属性
三、如何实现继承
1. 实现继承的基本思想
在js中我们使用实现继承(继承实际的方法)基于原型链进行继承
利用原型让一个引用类型继承另一个引用类型的属性和方法
2. 原型链
- 每个构造函数都有一个原型对象(原型对象有一个指向构造函数的指针)
- 每个实例都有一个指向原型对象的内部指针
- 将原型对象等于另一个类型的实例
此时的原型对象将包含着指向另一个原型的指针,另一个原型也包含着指向另一个构造函数的指针。
3. 原型系统
- 如果所有的对象都有私有字段(prototype),就是对象的原型
- 读取属性时,如果对象本身没有,则会继续访问对象的原型,直到原型为空或是找到为止
4. 操作原型的方法
- Object.create根据指定的原型创建新对象,原型可以是null
- Object.getPrototypeOf 获得一个对象的原型
- Object.setPrototypeOf 设置一个对象的原型
5. 默认的原型(数组方法是哪来的?)
所有的引用类型默认都继承了object
所有函数的默认原型都是object的实例,因此默认原型都会包含一个内部指针,指向object.porototype
这也是所有的自定义类型都会继承toString() valueOf() 的根本原因
6. 继承
a.使用构造器继承
function c1(){
this.p1 = 1;
this.p2 = function(){
console.log(this.p1);
}
}
var o1 = new c1;
o1.p2();
function c2(){
}
c2.prototype.p1 = 1;
c2.prototype.p2 = function(){
console.log(this.p1);
}
var o2 = new c2;
o2.p2();
new 运算符接收一个构造器和一组调用参数
- 以构造器的prototype 属性为原型,创建新对象
- 将this 和调用参数传给构造器
- 如果构造器返回的是对象则返回,否则,返回第一步创建的对象
b.使用类实现继承
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(this.name + ' barks.');
}
}
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
7. 原型链实现继承的情况下的搜索过程
- 搜索实例
- 搜索实例原型
- 搜索原型到最顶端找到该方法
如果找不到属性和方法的情况下,搜索过程总是要一环一环的进行到原型链末端才会结束
四、如何精确地判断一个变量的类型,typeof [] 输出是什么?为什么
1. typeof的判断结果有哪些?
对于基本数据类型,会直接返回类型 (null 和 undefined除外)
- string -string
- number - number
- boolean - boolean
- symbol - symbol
- void 0/未定义 - undefined
- null - object
- 函数 - 函数
2.typeof [] 输出object
a.如何检测数组?
- es5中 Array.isArray()
- [] instanceof Array
- object.prototype.toString.call([]) //[object Array]
console.log(typeof([])) //object
console.log(Array.isArray([])) //true
console.log([] instanceof Array) //true
console.log(Object.prototype.toString.call([])) //[object Array]
五、什么是模块化编程?
1. 模块化
- 模块化侧重于功能的封装,主要是针对js代码组装成一个个具有特定功能的模块。
- 模块可以通过传递不同的参数修改这个模块的功能的相关配置,每个模块都是一个单独作用域,根据需要时调用
- 模块一般是相互独立的,一般按照业务逻辑或者某个规范去进行划分
2. 组件化
- 页面的每个部分,比如头部,内容区,弹出框,确认按钮都可以成为一个组件,每个组件有独立的html,css,js代码
- 组件主要侧重于代码的复用,更多的是在视图上去展现
了解过Node.js没
Node 是一个让 JavaScript 运行在服务端的开发平台
1. node的优点
- node是基于事件驱动和无阻塞的,适合处理并发请求
- 与服务器交互的代码语言是由js编写的
2. node的缺点
- node是多线程的,所以不太稳定
CSS:
一、什么是盒模型
- width + height
- padding
- border
- margin
1. ie 盒子模型
border + padding + width = width(height同理)
2. 标准盒子模型
width就是内容的宽度
2. 什么情况下会造成dom元素高度塌陷?如何解决浮动布局导致的父元素高度塌陷问题?
float 浮动脱离了标准流造成父元素高度塌陷
如何解决浮动布局导致的父元素高度塌陷问题?
- 在浮动元素的后面再添加高度为0一个div,并且让他清除浮动 clear:both
- 给父元素设置overflow:hidden;
- 给父元素设置display:inline-block; (会包裹子元素)
- 给父元素设置一个伪类
.box:after{
content: "";
display: block;
clear: both;
}
或者下面这种:
.box:after{
content: ".";
display: block;
clear: both;
height: 0;//使父元素不会被.撑出来
overflow: hidden; //使.隐藏
}
了解flex布局吗?
弹性布局
如何实现一个自适应大小的正方形?
- 设置垂直方向的padding
.placeholder {
width: 100%;
height: 100vw;
}
- 设置垂直方向的 padding 撑开容器
.placeholder {
height: 0;//防止撑开容器
width: 100%;
padding-bottom: 100%;
}
- 利用伪元素的 margin(padding)-top 撑开容器
.placeholder {
width: 100%;
}
.placeholder:after {
content: '';
display: block;
margin-top: 100%; /* margin 百分比相对父元素宽度计算 */
}
补充
- content 属性专门应用在before /after 伪元素上,用来插入生成内容(最常见的是用来清除浮动)
- vw 是相对于视口宽度百分比的单位,1vw = 1% viewport width,
- vh 是相对于视口高度百分比的单位,1vh = 1% viewport height;
- vmin 是相对当前视口宽高中 较小 的一个的百分比单位,
- vmax 是相对当前视口宽高中 较大 的一个的百分比单位。
- em /ex em-height /x-height 常用的印刷度量单位(具有继承)
- 1 个em == 一种给定font-size 的值
- ex 是指所用字体中小写x 的高度
- rem是基于html元素的字体大小来决定
使用 em 和 rem 单位可以让我们的设计更加灵活,能够控制元素整体放大缩小,而不是固定大小。 我们可以使用这种灵
根元素的字体大小 16px,10rem 将等同于 160px,即 10 x 16 = 160。
如果一个 div 有 18px 字体大小,10em 将等同于 180px,即 10 × 18 = 180。
重点理解:
有一个比较普遍的误解,认为 em 单位是相对于父元素的字体大小。 事实上,根据W3标准 ,它们是相对于使用em单位的元素的字体大小。·
父元素的字体大小可以影响 em 值,但这种情况的发生,纯粹是因为继承。
总结em 和rem:
- rem 和 em 单位是由浏览器基于你的设计中的字体大小计算得到的像素值。
- em 单位基于font-size 的字体大小。
- rem 单位基于 html 元素的字体大小。
- em 单位可能受任何继承的父元素字体大小影响
- rem 单位可以从浏览器字体设置中继承字体大小。
- 使用 em 单位应根据组件的字体大小而不是根元素的字体大小。
- 在不需要使用em单位,并且需要根据浏览器的字体大小设置缩放的情况下使用rem。
- 使用rem单位,除非你确定你需要 em 单位,包括对字体大小。
- 媒体查询中使用 rem 单位
- 不要在多列布局中使用 em 或 rem -改用 %。
- 不要使用 em 或 rem,如果缩放会不可避免地导致要打破布局元素。
原文链接:http://caibaojian.com/rem-vs-em.html
如何让图片等比例缩放(指定比例,比如说1:1,不一定是图片原本的比例)
https://www.cnblogs.com/tugenhua0707/p/8387798.html
实现的基本原理:将使用到保持元素的宽高比的技巧,为元素添加垂直方向的padding-top的值,使用百分比的形式,这个值是相对于元素的宽而定的,比如我上面的一张图片的宽度是1024px,高度为316px;那么现在的
padding-top = (高度 / 宽度 )* 100% = (316 / 1024)* 100% = 30.85%;
但是仅仅对图片高度和宽度缩放的放还不够,我门还必须添加 background-size:cover, 使这个属性让背景铺满元素的,但是IE8及以下不支持该属性,因此为了兼容IE下面的浏览器,我门还需要再加一个属性 background-position: center ; 同时我门也要保证 图片的宽度最大等于父容器的宽度;因此下面的HTML代码如下:
- 1:1等比缩放
<style>
*{padding: 0;margin: 0;}
.demo{
width: 500px;
height: 500px;
border: 1px solid black;
}
.img{
width: 100%;
height: 0;
padding-top:100%;
overflow: hidden;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
-webkit-background-size: cover;
-moz-background-size: cover;
}
</style>
</head>
<body>
<div class="demo">
<div class="img" style="background-image: url(img/mf2.jpg)"></div>
</div>
</body>
- 4:3缩放
*{padding: 0;margin: 0;}
.demo{
width: 500px;
height: 500px;
border: 1px solid black;
}
.img{
width: 100%;
height: 0;
padding-top:75%;
overflow: hidden;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
-webkit-background-size: cover;
-moz-background-size: cover;
}
- 3:4 则就是
padding-top:133.33%