媒称,南京是一座现代化城市,但它有一种古老的蕴味,这座城市的历史遗韵使建筑与自然环境很和谐。
据英国广播公司网站5月13日报道,南京首次建都于公元229年,长期以来是中国最重要(和最大)的内河港口之一,也是公认的中国四大古都之一。这里发现了距今约60万年的直立人化石;明朝时期环绕这座城市的石头城墙距今已有600年的历史,而今仍然与现代的摩天大楼屹立在一起,使这座城市跟其复杂多变的过去有了永恒的视觉联系。
原籍英格兰设菲尔德、现居住在南京的中学教师弗雷娅·德鲁说:“从北京西路附近民国时期的低层建筑、新街口附近高耸的摩天大楼到老浦口蜿蜒的陋屋小巷,南京的建筑千差万别。”
<iframe data-filtered="filtered" frameborder="0" height="0" src="http://cpro.baidustatic.com/cpro/ui/c.html" width="0"></iframe>
报道称,虽然这种并列毗邻在其他城市可能看上去不协调,但在南京行得通。2018年来到这里的苏格兰教师埃德·库勒姆说:“这座城市的道路,往往绿树成荫,起起伏伏;老旧居住区紧挨着非常现代化的建筑。南京无疑是一座现代化城市,但它有一种古老的蕴味,这座城市的历史遗韵使建筑与自然环境很和谐。”
报道还称,作为一个外来人口不断增加的大学城,南京的节奏不同于熙熙攘攘的北京,也不同于极其新潮的上海,而是新来者乐于接受的平和折衷。
库勒姆解释说,尽管拥有830万人口,但南京是中国为数不多的很容易让人获得安宁和平静的大城市之一。他说:“在浦口(南京西北部的一个地区),坐30分钟的公共汽车就能把你送到老山风景区的边缘。这片大面积的森林覆盖的丘陵有许多小路和小径,很容易把喧闹的人群抛在身后。”
报道称,就在南京市中心,玄武湖提供了一个躲避喧嚣的安静之处,玄武湖公园内有寺庙、茶馆和餐厅。为了更好地了解南京的历史,库勒姆建议到老门东走一走,就在秦淮河以北,是一条经过整修的步行街。老门东是该市历史最悠久的商业街之一,其特色是拥有古典的木结构建筑(修旧如旧),内有纪念品商店,还有供应当地特色美食的小餐馆,比如盐水鸭、肉丸和美味糕点等等。
报道还称,与北京或西安的城墙不同,南京的老城墙不是几何形状的,而是绕着湖和山而建。因此,自然景观往往出现在意想不到的城区。像长江、钟山、玄武湖这些处于城市中心的自然景观给人带来的惊喜,正是新居民们喜欢生活在这里的原因所在。
库勒姆说:“对我来说,生活在南京意味着避开熙熙攘攘的大街,转入老街小巷,可能遇到几处院落、几泓碧水或几片幽林。正是这种巨大的多元性让南京具有了自己的魅力。”
库勒姆说,“对于喜欢避开线性基线重击声的人们”,这座城市还有许多低调的夜总会和现场音乐演出场所。对于想念老家食物的人来说,这里并不缺少迎合外国人和留学生的外国餐厅和咖啡馆。在城市里转一圈很容易。南京拥有一个覆盖该市大部分地区的高效、宽敞的地铁系统,不过自行车也是一个选项,这里有适合骑车的宽阔、笔直的道路。
原标题:外国人眼中的古都南京:历史文化和现代生活融为一体
优点:
缺点:
HTML 提供了一系列内置的元素(如 <div>、<p> 等),而自定义元素则是由开发者自定义的,可以用来扩展 HTML 语义和功能。
在传统的 HTML 中,我们只能使用已定义的标签来创建元素,如 <div>、<p>、<span> 等。但随着 Web 技术的不断发展,HTML5 引入了自定义元素的功能,允许开发者创建自己的标签,并赋予其特定的行为和样式。
带你用最简单的方式理解最全面的BFC哔哩哔哩bilibili
BFC,即块级格式化上下文(Block Formatting Context),是CSS中的一个概念。它是指一个独立的渲染区域,其中的元素按照一定的规则进行布局和渲染。
BFC的主要作用是控制元素在布局上的行为,包括外边距的塌陷、浮动元素对周围元素的影响以及清除浮动等。以下是BFC的一些特性和应用:
创建BFC的方式有多种,包括:
总而言之,BFC是一种控制元素布局行为的机制,它可以解决一些常见的布局问题,如外边距塌陷、浮动元素重叠等。了解BFC的使用和原理对于前端开发中复杂布局的实现非常有帮助。
① 使用Flexbox:通过将父容器设置为display: flex;,然后使用justify-content: center;和align-items: center;属性来水平和垂直居中子元素。
.parent {
display: flex;
justify-content: center;
align-items: center;
}
② 使用Grid布局:通过将父容器设置为display: grid;,然后使用place-items: center;属性来水平和垂直居中子元素。
.parent {
display: grid;
place-items: center;
}
③ 使用绝对定位和transform属性:将子元素的位置设置为绝对定位,并且使用top: 50%;和left: 50%;将元素的左上角移动到父容器的中心,然后使用transform: translate(-50%, -50%);将元素的中心与父容器的中心对齐。
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
④ 使用表格布局:将父容器设置为display: table;,然后将子元素设置为display: table-cell;和vertical-align: middle;以实现水平和垂直居中。(文本水平垂直居中)
.parent {
display: table;
}
.child {
display: table-cell;
vertical-align: middle;
text-align: center;
}
⑤父flex + 子margin:auto
⑥绝对定位均设0 + margin:auto
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/*
思路:
1、容器宽度设为100%来填充整个页面宽度
2、为左右中三者设置float:left,以此可以显示在一行
3、为left和right部分设置负的margin值,让它们移到center行中,但注意,现在的left和right将center左右部分覆盖了
4、解决覆盖问题,有两种方式:
(1) 为center左右设置内边距,但这时会将页面撑大,所以我们要将内边距合并到100%的宽度里,这里我们想到了用怪异盒模型
(2) 用定位的方式解决,为容器wrapper设置内边距,然后为left和right设置相对定位,并为其移动到左右两边
扩展:
与双飞翼布局的区别?
圣杯布局通过设置负边距与容器内边距来使三栏显示于一列,而双飞翼布局则为中间列额外包裹添加外边距来防止左右两侧遮挡,两者实现效果相似
*/
.item {
height: 100px;
/* 这里设置浮动是为了让三者可以并排显示 */
float: left;
}
.center {
/* 为了防止左右两块与center重叠,我们要为其设置内边距 */
/* padding: 0 300px; */
/* 方式一:将盒子模型设为怪异盒模型,防止padding将左右顶开 */
/* box-sizing: border-box; */
}
.center {
width: 100%;
background-color: green;
}
.wrap {
padding:0 300px;
}
.left {
width: 300px;
background-color: yellow;
/* 为了让left块和center在同一行,需要用负的margin值让它向回移动 */
margin-left: -100%;
/* 方式二:设relative */
position: relative;
left: -300px;
}
.right {
width: 300px;
background-color: red;
/* 为了让right块和center在同一行,需要用负的margin值让它向回移动 */
margin-left: -300px;
/* 方式二:设relative */
position: relative;
right: -300px;
}
</style>
</head>
<body>
<!-- 圣杯布局分左右中三部分 -->
<div class="wrap">
<!-- 为了让中间内容先渲染,写在上面 -->
<div class="item center"></div>
<div class="item left"></div>
<div class="item right"></div>
</div>
</body>
</html>
.clearfix::after {
content: "";
clear: both;
display: block;
}
clearfix通过为父元素添加伪元素,并为其添加清除浮动效果来解决浮动元素引起的高度塌陷问题,这里设置display:table主要有两方面作用:
对于轴线:
对于其中的每一项:
浮动的原理是让图片脱离文档流,直接浮在桌面上。我们一般布局的时候都是只设置宽度不设置高度,让内容来自动填充高度。但使用浮动后会让原本填充的高度消失,父元素高度为0,后续添加内容布局会产生混乱,造成高度塌陷,这时候就可以利用清除浮动来解决父元素高度塌陷的问题。
浮动导致的问题及其解决方案:
.clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden;
}
.clearfix{
*zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/
}
①定义grid布局:
②设置行与列的布局
③划分区域自定义放置元素
grid-template-columns: 120px 120px 120px;
grid-template-rows: repeat(3, 300px);
grid-template-areas:
". header header"
"sidebar content content"
"sidebar . .";
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
④划分区域自动填充元素
⑤自由安排元素位置
⑥所有元素在单元格内的对齐方式
⑦单个元素在单元格内的对齐方式
⑧单元格在容器内的对齐方式
⑨多出来的东西怎么放?隐式网格
一些面试题
基本选择器:id class 标签 层次选择器:后代、子代、兄弟、通用 结构选择器:第一个、最后一个、奇数偶数个、伪类、伪元素 属性选择器:属性
CSS 的 animation 属性用于为元素添加动画效果。以下是 animation 属性的一些常用子属性:
1、animation-name: 定义动画的名称。
.animation {
animation-name: myAnimation;
}
@keyframes myAnimation {
0% { opacity: 0; }
100% { opacity: 1; }
}
2、animation-duration: 定义动画的持续时间。
.animation {
animation-name: myAnimation;
animation-duration: 2s;
}
3、animation-timing-function: 定义动画的时间函数(即动画进度的加速度)。
.animation {
animation-name: myAnimation;
animation-timing-function: ease-in-out;
}
4、animation-delay: 定义动画开始之前的延迟时间。
.animation {
animation-name: myAnimation;
animation-delay: 1s;
}
5、animation-iteration-count: 定义动画的播放次数,infinite为永不停止。
.animation {
animation-name: myAnimation;
animation-iteration-count: 3;
}
6、animation-direction`: 定义动画的播放方向。
.animation {
animation-name: myAnimation;
animation-direction: reverse;
}
7、animation-fill-mode: 定义动画在播放之前和之后如何应用样式。
.animation {
animation-name: myAnimation;
animation-fill-mode: forwards;
}
8、animation-play-state: 定义动画的播放状态。
.animation {
animation-name: myAnimation;
animation-play-state: paused;
}
这些是 animation 属性的一些常用子属性,它们可以用来控制动画的各个方面,从而创建出丰富多样的动画效果。使用这些属性可以自定义动画的外观、持续时间、延迟等。要实现动画效果,还需要定义动画的关键帧(@keyframes)规则,包含动画在不同百分比时的样式。
在 CSS 中,可以使用 @keyframes 规则来定义动画的关键帧(即动画的不同阶段)。@keyframes 规则定义了动画的每个关键帧以及相应的样式。
下面是一个使用 @keyframes 定义动画关键帧的示例:
@keyframes slide {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
100% {
transform: translateX(200px);
}
}
在这个例子中,我们创建了一个名为 slide 的动画。通过 @keyframes 规则,我们定义了三个关键帧:0%、50% 和 100%。
你可以在关键帧中定义任意数量的状态,并根据需要设置不同的样式属性。使用百分比来表示关键帧的时间点,动画会根据关键帧之间的插值进行平滑过渡。
定义完关键帧后,你可以使用 animation-name 属性将动画应用到具体的元素上,如下所示:
.element {
animation-name: slide;
animation-duration: 2s;
}
通过将 animation-name 设置为关键帧名称,你可以将定义好的动画应用于元素,并设置动画的持续时间(在此示例中为 2 秒)。
请注意,在实际使用中,除了设置关键帧的样式,你还可以使用其他属性调整动画的速度、延迟、重复次数等。根据具体需求,你可以进一步完善动画效果。
CSS 的 transition 属性用于在元素发生状态变化时,平滑地过渡(或动画)到新的样式。它允许你控制一个或多个 CSS 属性的变化过程,使得元素的变化更加柔和和可控。
transition 属性由以下几个子属性组成:
1、transition-property:指定要过渡的 CSS 属性名称,可以是单个属性,也可以是多个属性。 当 transition 属性只设置了 transition-duration 值时,没有指定 transition-property 值,默认情况下所有可过渡的 CSS 属性都会应用过渡效果。
.element {
transition-property: width;
}
2、transition-duration:指定过渡的持续时间,以秒(s)或毫秒(ms)为单位。
.element {
transition-duration: 0.5s;
}
3、transition-timing-function:指定过渡的时间函数,用于控制过渡的速度曲线。常见的值包括 ease(默认值)、linear、ease-in、ease-out 和 ease-in-out,也可以使用贝塞尔曲线来定义自定义的速度曲线。
.element {
transition-timing-function: ease-in-out;
}
4、transition-delay:指定过渡开始之前的延迟时间,以秒(s)或毫秒(ms)为单位。
.element {
transition-delay: 0.2s;
}
通过使用这些子属性,你可以控制元素的过渡效果,从而实现例如悬停时颜色渐变、尺寸变化、透明度渐变等效果。
例如,下面的代码演示了一个当鼠标悬停在元素上时,背景颜色发生渐变过渡的效果:
.element {
background-color: blue;
transition-property: background-color;
transition-duration: 0.5s;
transition-timing-function: ease-in-out;
}
.element:hover for(let [key, value] of map) {
if(largeStr.indexOf(key)!==-1) {
}
}
background-color: red;
}
以上代码将使元素的背景颜色在悬停时从蓝色平滑地过渡到红色,过渡时间为 0.5 秒,速度曲线为先加速后减速。这只是 transition 属性的一个简单示例,你可以根据需要调整和组合这些子属性来实现更复杂的过渡效果。
外边距塌陷是指在垂直方向上,两个相邻元素的外边距(margin)合并成一个外边距的现象。以下是几种常见的外边距塌陷情况及其解决方案:
这些解决方案的原理都是通过改变元素的布局特性来创建新的块级格式化上下文(BFC),从而阻止外边距的合并。BFC 可以独立地控制元素的布局行为,使得外边距不再发生塌陷。
伪类: 用于已有元素处于某种状态时为其添加对应的样式,这个状态是根据用户行为而动态变化的
例如:当用户悬停在指定元素时,可以通过:hover来描述这个元素的状态,虽然它和一般css相似,可以为 已有元素添加样式,但是它只有处于DOM树无法描述的状态下才能为元素添加样式,所以称为伪类
伪元素: 用于创建一些不在DOM树中的元素,并为其添加样式
例如,我们可以通过:before来在一个元素之前添加一些文本,并为这些文本添加样式,虽然用户可以看见 这些文本,但是它实际上并不在DOM文档中
综上所述,<link> 更适合引入外部资源,而 @import 更适合在 CSS 文件中嵌入其他 CSS 文件。如果需要同时加载多个 CSS 文件,最好使用 <link>,以提高页面的性能和可访问性。
对象(Object):JavaScript 的对象是一种复合数据类型,用于存储键值对。对象由一组属性(properties)组成,每个属性都有一个键(key)和对应的值(value)。对象可以通过字面量表示法或构造函数来创建。
函数(Function):JavaScript 是一门函数式编程语言,函数在 JavaScript 中是一等公民。函数是可执行的代码块,可以接收参数并返回一个值。可以通过函数声明或函数表达式的方式定义函数。
数组(Array):JavaScript 数组是一种有序、可变的数据集合,可以存储多个值。数组可以包含不同类型的数据,并且长度是动态的。可以使用字面量表示法或构造函数来创建数组。
隐式类型转换是指 JavaScript 在比较或计算操作中自动将一个数据类型转换为另一个数据类型。这种类型转换是根据 JavaScript 的类型转换规则进行的,以下是一些常见的隐式类型转换规则:
==
运算
补充问题:
当a为多少时,if判断成立
let a
if(a == 1&&a == 2&&a == 3) {
console.log('success!')
}
答案:
a = {
a:1,
valueOf() {
return a++
}
}
var c = 1;
function c(c) {
console.log(c)
}
c(2)
//函数作⽤域:局部作⽤域
var a = 1;
function b() {
a = 10;
return;
//a函数声明,提前变量a,将a认为是函数b作⽤域的变量,具有局部效果
function a(){}
}b();
console.log(a); // 1
var m= 1, j = k = 0;
function add(n) {
return n = n+1;
}
y = add(m);
function add(n) {
return n = n + 3;
}
z = add(m);
跨域请求是指在浏览器中,当请求的源地址与请求地址的协议、域名、端口号不一致时,会被浏览器的同源策略所限制,这是为了保护用户的信息安全。
响应式设计(Responsive Design)是一种网页设计和开发的方法,旨在使网站能够适应不同设备、屏幕尺寸和浏览器窗口大小,以提供更好的用户体验。响应式设计通过使用灵活的布局、弹性的图像和媒体查询等技术,让网页能够根据用户设备的特性进行自适应和优化。
在开发响应式网站时,需要考虑以下几个方面:
以下是一些常用的技术和方法来实现响应式设计:
单页面应用(Single Page Application,SPA)是一种Web应用程序的架构模式,它在加载初始HTML页面后,通过JavaScript动态地更新页面的内容,而不需要每次页面切换时重新加载整个页面。
与传统的多页面应用相比,SPA有以下优势:
然而,SPA也存在一些劣势:
原型关系:
原型: 在 JS 中,每当定义一个对象(函数也是对象)时,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。
原型链:函数的原型对象上的constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针_proto_ ,该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似。因此可以利用_proto_ 一直指向Object的原型对象上,而Object原型对象用Object.prototype.__ proto__ = null表示原型链顶端。如此形成了js的原型链继承。同时所有的js对象都有Object的基本方法
特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
事件委托(或称事件代理)是一种在前端开发中常用的技术,它利用了事件冒泡机制,将事件处理程序绑定到一个父元素上,而不是直接绑定到每个子元素上。当事件触发时,事件会经过冒泡阶段依次向上传播至父元素,父元素可以根据事件的目标元素来判断应该执行哪个事件处理函数。
事件委托的作用主要有以下几点:
举个例子,假设有一个列表的父元素,里面包含了多个子元素(项),我们需要为每个子元素绑定点击事件,实现点击子元素时改变其样式。使用事件委托可以这样处理:
// 获取父元素
const parentElement = document.getElementById('parent');
// 绑定点击事件到父元素
parentElement.addEventListener('click', function(event) {
// 判断事件目标是否是子元素(项)
if (event.target && event.target.nodeName === 'LI') {
// 执行事件处理逻辑,例如改变样式
event.target.classList.toggle('active');
}
});
通过将点击事件绑定到父元素上,无论新增或删除了子元素,甚至是动态生成的子元素,都会自动触发相应的事件处理逻辑,大大简化了代码的管理和维护。
Codeconst [a, b] = [1, 2];
也可以通过以下方式提取对象属性:
Codeconst { name, age } = { name: 'Alice', age: 18 };
Codeconst name = 'Alice';
console.log(`Hello, ${name}!`);
Codeconst arr = [1, 2, 3];
console.log(...arr); // 输出:1 2 3
Codeclass Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}!`);
}
static getInfo() {
console.log('This is a person class.');
}
}
const person = new Person('Alice');
person.sayHello(); // 输出:Hello, my name is Alice!
Person.getInfo(); // 输出:This is a person class.
Codeconst name = 'Alice';
const age = 18;
const person = { name, age };
console.log(person); // 输出:{ name: 'Alice', age: 18 }
// moduleA.js
export function greet(name) {
console.log(`Hello, ${name}!`);
}
// moduleB.js
import { greet } from './moduleA.js';
greet('Alice'); // 输出:Hello, Alice!
function fetchData() {
return new Promise((resolve, reject) => {
// 异步操作...
if (/* 异步操作成功 */) {
resolve('Data fetched successfully!');
} else {
reject('Failed to fetch data!');
}
});
}
fetchData()
.then(data => console.log(data)) // 成功时执行
.catch(error => console.error(error)) // 失败时执行
.finally(() => console.log('Done')); // 不论成功与否都执行
javascript Codeconst numbers = [1, 2, 3, 4];
numbers.forEach(num => console.log(num)); // 遍历输出每个元素
const doubledNumbers = numbers.map(num => num * 2); // 对每个元素进行操作并返回新数组
const evenNumbers = numbers.filter(num => num % 2 === 0); // 过滤出符合条件的元素
const sum = numbers.reduce((acc, num) => acc + num, 0); // 对数组进行累加
apply、call 和 bind 都是 JavaScript 中用于改变函数执行上下文(this)的方法,它们的区别如下:
总结:
在 JavaScript 中,基本数据类型(Primitive Types)和引用数据类型(Reference Types)在处理和操作时有所不同。当我们对基本数据类型值进行属性访问或方法调用时,JavaScript 会将基本数据类型自动转换为对应的包装对象,这个过程称为装箱(Boxing)。
下面以数字类型(Number)为例,简要说明基本数据类型装箱的过程:
装箱的过程是自动发生的,JavaScript 引擎会在需要时自动执行装箱和拆箱操作,使得开发者能够像操作引用类型一样操作基本类型。而这种装箱和拆箱的过程在后台进行,对于开发者来说是透明的。
需要注意的是,由于装箱过程涉及到对象的创建和数据拷贝,相比于直接操作基本类型,使用包装对象会带来额外的开销。因此,在不必要的情况下,最好直接操作基本类型,而不是通过装箱和拆箱操作。
JavaScript中的最大安全整数是 9007199254740991。它可以使用 Number.MAX_SAFE_INTEGER 常量来表示。这个值是由 JavaScript 中的双精度浮点数表示法决定的,在进行数值运算时不会丢失精度。
超过最大安全整数的数值会导致精度丢失,可能会引发意外的结果。如果需要处理超过最大安全整数范围的大整数,可以使用第三方的大数库或者 BigInt 类型(ES2020 新增)来处理。BigInt 类型可以表示任意精度的整数,但是在进行数值计算时需要特别注意性能和兼容性的问题。
CommonJS(简称CJS)和ES Modules(简称ESM)是两种不同的模块化规范,有以下不同:
补充:相同点——CJS和ESM导入时,都会将整个模块的代码执行一遍,然后缓存执行的结果
每个node.js文件在执行时都会隐式的、自动的创造一个module对象,同时,module对象会创建一个名叫exports,初始值为{}的属性:
var module = {
exports:{}
}
为了可以更好的导出对应功能模块里的内容,它会又隐式的创建一个变量exports:
//隐式的创建了一个变量exports
var exports = module.exports
//此时exports和module.exports 引用的是同一个对象
console.log(exports === modules.exports) //true
所以我们通过exports.xxx = xxx的方式进行导出,它最终也是被加到了modules.exports对象中
最终导出的是modules.exports对象,这就意味着如果我们将exports的指向改变,那么通过exports.xxx = xxx添加的导出就不会再添加到modules.exports对象中,xxx也就不会被导出
JS是一门单线程语言,因为它运行在浏览器的渲染主线程中(当遇到JS代码时,渲染主线程会将控制权交给js引擎来处理),而渲染主线程只有一个。
而渲染主线程承担着诸多工作,渲染页面,执行js都在其中执行。
如果用同步的方式,极有可能导致主线程产生阻塞,从而导致消息队列中很多任务无法及时执行。
所以浏览器就采取了异步措施,当某些异步任务触发时,如定时器、网络请求、事件监听器等,主线程就会将任务交给其他线程去处理,自身立即结束任务执行,转而执行后续任务,等到异步任务执行完毕,将事先传递的回调函数包装成任务,加入到对应队列(延时队列、微任务队列、交互队列)的末尾排队,等待主线程调度执行。
在这种异步模式下,浏览器就不会发生阻塞,保证了单线程的流畅运行。
事件循环又叫消息循环,是浏览器渲染主线程的工作方式。
在Chrome的底层实现中,它开启了一个for的死循环,每次循环从消息队列中取出第一个任务执行,而其他线程只需要在合适的时机将任务放到消息队列中。
以前我们会将消息队列简单分为宏任务队列和微任务队列,现在随着浏览器环境愈发复杂,浏览器采用了更加灵活多变的处理方式。
根据W3C官方解释,每个任务都有不同的类型,同类型的任务须在同一个队列。不同的队列有不同的优先级(例如交互队列优先级大于延时队列),在一次事件循环中,由浏览器自行决定取哪一个队列的任务,但浏览器必须有一个微任务队列,且其优先级是最高的,必须优先调度执行。
不可以
如果使用常规的Object.getOwnPropertyNames()来判断,虽然可以将一般的不可枚举类型属性也判断出来,但无法判断继承的属性以及Symbol类型值定义的属性。所以我们需要使用Reflect.ownKeys()来进行转换,这样通过它返回的数组长度就能精准判断出对象是否为空。
1、正则
String.prototype.trim = function() {
return this.replace(/(^\s*)|(\s*$)/g, "")
}
2、双指针法
.精灵图(CSS Sprites)的优点和缺点
精灵图是一种网页图片应用处理方式。就是把网页中很多小背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background-repeat”,“background-position”的组合进行背景图显示及定位,达到显示某一部分背景图的效果。
精灵图的优点:
1、减少图片的体积,因为每个图片都有一个头部信息,把多个图片放到一个图片里,就会共用同一个头部信息,从而减少了字节数。
2、减少了网页的http请求次数,从而加快了网页加载速度,提高用户体验。
3、解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不需要对每一个小元素进行命名,从而提高了网页的制作效率。
4、更换风格方便,只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变。维护起来更加方便。
精灵图的缺点:
1.在图片合并的时候,你要把多张图片有序的合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景;这些还好,最痛苦的是在宽屏,高分辨率的屏幕下的自适应页面,你的图片如果不够宽,很容易出现背景断裂;
2.在开发的时候比较麻烦,你要通过photoshop或其他工具测量计算每一个背景单元的精确位置,这是针线活,没什么难度,但是很繁琐;
3.在维护的时候比较麻烦,如果页面背景有少许改动,一般就要改这张合并的图片,无需改的地方最好不要动,这样避免改动更多的css,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动css。
4.精灵图不能随意改变大小和颜色。精灵图改变大小会失真模糊,降低用户体验,css3新属性可以改变精灵图颜色,但是比较麻烦,并且新属性有兼容问题。现在一般都是用web字体(图标字体)来代替精灵图。
2.什么是vue全家桶
Vue + vue-router + vuex + axios + es6 + sass
3.doctype是什么,网页常见doctype及特点
DOCTYPE是document type(文档类型)的简写,在web设计中用来说明你用的XHTML或者HTML是什么版本。
常见类型:
1.过渡型(Transitional):要求非常宽松,它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法),完整代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2.严格型(Strict):要求非常严格,你不能使用任何表现层的标识和属性,例如<br>,完整代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3.框架型(Frameset):专门针对框架页面设计使用,如果你的页面中包含有框架(frameset),完整代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3.什么是web语义化,有什么好处
Web语义化简单来说就是为了让页面对人和机器更友好,让人和机器更容易理解页面内容。
1.对机器来说,语义化能让机器更精确的知道页面中的重点和关键点。让机器更容易为人筛选出想要的部分。
2.对开发人员来说,更容开发和易维护页面。根据页面中的标签名和类名就能知道哪个部分放置了哪些内容,从而提高了开发和维护的效率。
4.你知道的HTTP 请求方式有几种
HTTPRequestMethod共计17种
1.GET 请求指定的页面信息,并返回实体主体。
2.HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
3.POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
4.PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5.DELETE 请求服务器删除指定的页面。
6.CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
7.OPTIONS 允许客户端查看服务器的性能。
8.TRACE 回显服务器收到的请求,主要用于测试或诊断。
9.PATCH 实体中包含一个表,表中说明与该URI所表示的原内容的区别。
10.MOVE 请求服务器将指定的页面移至另一个网络地址。
11.COPY 请求服务器将指定的页面拷贝至另一个网络地址。
12.LINK 请求服务器建立链接关系。
13.UNLINK 断开链接关系。
14.WRAPPED 允许客户端发送经过封装的请求。
15.LOCK 允许用户锁定资源,比如可以再编辑某个资源时将其锁定,以防别人同时对其进行编辑。
16.MKCOL 允许用户创建资源
17.Extension-mothed 在不改动协议的前提下,可增加另外的方法。
5.css选择器有哪些
1.简单选择器
通配符选择器 *
id选择器 #id
class选择器 .class
标签选择器 element
2.复合选择器
后代选择器 element element
子代选择器 element>element
兄弟选择器 element+element
并列选择器 element,element
伪类选择器 :link
属性选择器 [attribute]
6.css hack原理及常见hack
原理:CSS hack是一种类似作弊的手段,以欺骗浏览器的方式达到兼容的目的,是用浏览器的兼容性差异来解决浏览器的兼容性问题。
常见hack:
1.利用浏览器对相同代码的解析和支持的不同实现的hack
比如div{ _width:80px },在ie6中能识别并解析带下划线的属性,但是ie7及以上版本中识别不了。
2.以Firefox或Webkit特有的扩展样式实现的hack
如Firefox支持以-moz-开头的属性
Webkit内核支持以-webkit-开头的属性
3.以IE特有的条件注释为基础的hack
<!--[ifIE8]> <style type="text/css"> #test{ color:red; } </style><![endif]-->
比如这个样式,可以在ie8中生效,但是其他浏览器则不会生效
7.css中有哪些常见的继承属性
文本
color(颜色,a元素除外)
direction(方向)
font(字体)
font-family(字体系列)
font-size(字体大小)
font-style(用于设置斜体)
font-variant(用于设置小型大写字母)
font-weight(用于设置粗体)
letter-spacing(字母间距)
line-height(行高)
text-align(用于设置对齐方式)
text-indent(用于设置首航缩进)
text-transform(用于修改大小写)
visibility(可见性)
white-space(用于指定如何处理空格)
word-spacing(字间距)
列表
list-style(列表样式)
list-style-image(用于为列表指定定制的标记)
list-style-position(用于确定列表标记的位置)
list-style-type(用于设置列表的标记)
表格
border-collapse(用于控制表格相邻单元格的边框是否合并为单一边框)
border-spacing(用于指定表格边框之间的空隙大小)
caption-side(用于设置表格标题的位置)
empty-cells(用于设置是否显示表格中的空单元格)
页面设置(对于印刷物)
orphans(用于设置当元素内部发生分页时在页面底部需要保留的最少行数)
page-break-inside(用于设置元素内部的分页方式)
widows(用于设置当元素内部发生分也是在页面顶部需要保留的最少行数)
其他
cursor(鼠标指针)
quotes(用于指定引号样式)
8.sessionStorage,localStorage,cookie区别
·共同点:都是保存在浏览器端,且同源的。
·区别:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递;cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。
·而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
·数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
·作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。WebStorage 支持事件通知机制,可以将数据更新的通知发送给监听者。WebStorage的 api 接口使用更方便。
9.JavaScript有哪些数据类型
原始类型有6种 object,number,string,boolean,null,undefined
10.输出今天是星期几
var str = "今天是星期" + "日一二三四五六".charAt(new Date().getDay());alert(str);
11.如何判断一个变量是否为数组
arr.constructor === Array 为true说明是数组类型
arr instanceof Array 为true则是数组类型
Object.prototype.toString.call(arr) === '[object Array]'; 为true为数组类型
Array.isArray(arr) 为true则为数组类型
12.实现一个js深度克隆函数
//深度克隆
function deepClone(obj){
var result={},oClass=isClass(obj);
for(key in obj){
var copy=obj[key];
if(isClass(copy)=="Object"){
result[key]=arguments.callee(copy);
}else if(isClass(copy)=="Array"){
result[key]=arguments.callee(copy);
}else{
result[key]=obj[key];
}
}
return result;
}
function isClass(o){
if(o===null) return "Null";
if(o===undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8,-1);
}
//克隆一个数组
var arr=["a","b","c"];
var oNew=deepClone(arr);
console.log(oNew);//Object {0: "a", 1: "b", 2: "c"}
13.给定一个日期,页面打印倒计时
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>倒计时</title>
</head>
<body>
<input type="text" name="time" id="time" value="2017-09-22" />
<input type="button" name="okbtn" id="okbtn" value="确认" />
<br />
<p id="textp">这里显示倒计时</p>
</body>
<script type="text/javascript">
var okbtn=document.getElementById("okbtn");
textp=document.getElementById("textp");
okbtn.onclick=function(){
var time=document.getElementById("time");
var timevalue=time.value;
//通过正则表达式确认输入格式是否正确
var patt=/^(\d{1,4})(-)(\d{1,2})(\d{1,2})$/;
if(patt.test(timevalue)==false){
//如果不正确
textp.innerHTML="输入格式不满足YYYY-MM-DD";
return false;
}else{
textp.innerHTML="这里显示倒计时";
}
//获取输入的年月日
var timearray=timevalue.split("-");
//ShowLeftTime(timearray[0],timearray[1],timearray[2]);
setInterval(function(){ShowLeftTime(timearray[0],timearray[1],timearray[2]);},1000);
}
function ShowLeftTime(year,month,date){
//得出剩余时间
var now=new Date();
var endDate=new Date(year,month-1,date);
var leftTime=endDate.getTime()-now.getTime();
var leftsecond=parseInt(leftTime/1000);
var day=Math.floor(leftsecond/(60*60*24));
var hour=Math.floor((leftsecond-day*24*60*60)/3600);
var minute=Math.floor((leftsecond-day*24*60*60-hour*3600)/60);
var second=Math.floor(leftsecond-day*60*60*24-hour*60*60-minute*60);
//显示剩余时间
textp.innerHTML="距离"+year+"年"+month+"月"+date+"日"
+"还有"+day+"天"+hour+"小时"+minute+"分"+second+"秒";
}
</script>
</html>
14.数组去重
//利用indexOf
var aa=[1,3,5,4,3,3,1,4]
function arr(arr) {
var result=[]
for(var i=0; i<arr.length; i++){
if(result.indexOf(arr[i])==-1){
result.push(arr[i])
}
}
console.log(result)
}
arr(aa)
//循环嵌套
function fn(arr) {
var result = [];
var flag;
for (var i = 0, len = arr.length; i < len; i++) {
flag = false;
for (var j = 0, len = result.length; j < len; j++) {
if (arr[i] == result[j]) {
flag = true;
break;
}
}
if (!flag) {
result.push(arr[i]);
}
}
return result;
}
15.求数组中最大值,最小值和重复次数最多的数值
var arr = [1,2,2,3,5,5,5,6];
var max = arr[0]; // 数组中的最大值
var min = arr[0]; // 数组中的最小值
var mostCount; // 数组中出现次数最多的元素
var temp = {};
var num = 0;
for(var i=arr.length-1; i>=0; i--){
if(max<arr[i]){ // 得到最大值
max = arr[i]
}
if(min>arr[i]){ // 得到最小值
min = arr[i]
}
if(temp[arr[i]]){ // 得到元素出现的次数,并组成obj
temp[arr[i]] = tempObj[arr[i]]+1;
}else{
temp[arr[i]] = 1;
}
}
for(var key in temp){ // 从对象中得到数组中出现最多的元素
if(!mostCount){
mostCount = key;
}else if(temp[mostCount]<temp[key]){
mostCount = key;
}
}
console.log("最大值为"+max+"; 最小值为"+minVal+"; 次数最多的为"+mostCount);
17.请概括什么情况下打印控制台会提示undefined
1.当打印的变量声明未赋值时
2.当打印的执行函数没有返回值时
18.原生实现数组快速排序
var times=0;
var quickSort=function(arr){
//如果数组长度小于等于1无需判断直接返回即可
if(arr.length<=1){
return arr;
}
var midIndex=Math.floor(arr.length/2);//取基准点
var midIndexVal=arr.splice(midIndex,1);//取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数arr[index+1]
var left=[];//存放比基准点小的数组
var right=[];//存放比基准点大的数组
//遍历数组,进行判断分配
for(var i=0;i<arr.length;i++){
if(arr[i]<midIndexVal){
left.push(arr[i]);//比基准点小的放在左边数组
}
else{
right.push(arr[i]);//比基准点大的放在右边数组
}
console.log("第"+(++times)+"次排序后:"+arr);
}
//递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;
return quickSort(left).concat(midIndexVal,quickSort(right));
};
console.log(quickSort(arr));
19.原生实现二分查找法
var arr = [5,0,-56,90,12];
var flag = false;//标志位进行优化,数组本来就是有序序列的话,无需再排序
//先进行大的排序
for(var i=0;i<arr.length-1;i++){
//小的排序
for(var j=0;j<arr.length-1-i;j++){
//比较
if(arr[j]>arr[j+1]){
//交换
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = true;
}
}
//此部分为优化,已排序的话,无需再次排序
if(flag){
flag=false;
}else{
break;//已排序,无需交换
}
}
//输出新数组
for(var i=0;i<arr.length;i++){
document.write(arr[i]+' ');
}
20.正则表达式,清楚字符串前后空格
var str=" hello ";
str=str.replace(/^s*|s*$/g,'');
alert(str);
21.简述http协议中get和post方法的区别
1、 GET主要用于从服务器查询数据,POST用于向服务器提交数据
2、 GET通过URL传递数据,POST通过http请求体传递数据
3、 GET传输数据量有限制,不能大于2kb,POST传递的数据量较大,一般大量的数据提交都是通过POST方式
4、 GET安全性较低,容易在URL中暴漏数据,POST安全性较高
22.什么是csrf攻击,如何阻止
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
防止方式
(1).Cookie Hashing(所有表单都包含同一个伪随机值)
(2).验证码
(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
23.服务器推送数据到前端有哪些解决方案
一、Ajax轮询
用定时器不断发送请求
优点:实现简单。
缺点:这是通过模拟服务器发起的通信,不是实时通信,不顾及应用的状态改变而盲目检查更新,导致服务器资源的浪费,且会加重网络负载,拖累服务器。
二、comet
基于 HTTP 长连接的 "服务器推" 技术,能使服务器端主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求,目前有两种实现方式:
1. 基于 AJAX 的长轮询(long-polling)方式
优点
客户端很容易实现良好的错误处理系统和超时管理,实现成本与Ajax轮询的方式类似。
缺点
需要服务器端有特殊的功能来临时挂起连接。当客户端发起的连接较多时,服务器端会长期保持多个连接,具有一定的风险。
2. 基于 Iframe 及 htmlfile 的流(streaming)方式
Comet的优缺点
优点: 实时性好(消息延时小);性能好(能支持大量用户)
缺点: 长期占用连接,丧失了无状态高并发的特点。
三、websocket
WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通讯协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
24.h5c3有哪些新增特性
h5新增的标签
新增元素 | 说明 |
video | 表示一段视频并提供播放的用户界面 |
audio | 表示音频 |
canvas | 表示位图区域 |
source | 为video和audio提供数据源 |
track | 为video和audio指定字母 |
svg | 定义矢量图 |
code | 代码段 |
figure | 和文档有关的图例 |
figcaption | 图例的说明 |
main | |
time | 日期和时间值 |
mark | 高亮的引用文字 |
datalist | 提供给其他控件的预定义选项 |
keygen | 秘钥对生成器控件 |
output | 计算值 |
progress | 进度条 |
menu | 菜单 |
embed | 嵌入的外部资源 |
menuitem | 用户可点击的菜单项 |
menu | 菜单 |
template | 模板 |
section | 区块 |
nav | 导航 |
aside | 侧边栏 |
article | 文章 |
footer | 底部 |
header | 头部 |
- css3
css3被划分为模块,最重要的几个模块包括:选择器、框模型、背景和边框、文本效果、2D/3D 转换、动画、多列布局、用户界面
选择器
框模型
背景和边框
border-radius、box-shadow、border-image、
background-size:规定背景图片的尺寸
background-origin:规定背景图片的定位区域
background-clip:规定背景的绘制区域
文本效果(常用)
text-shadow:设置文字阴影
word-wrap:强制换行
word-break
css3提出@font-face规则,规则中定义了font-family、font-weight、font-style、font-stretch、src、unicode-range
2/3D转换
transform:向元素应用2/3D转换
transition:过渡
动画
@keyframes规则:
animation、animation-name、animation-duration等
用户界面(常用)
box-sizing、resize
css3新增伪类
:nth-child()
:nth-last-child()
:only-child
:last-child
:nth-of-type()
:only-of-type()
:empty
:target 这个伪类允许我们选择基于URL的元素,如果这个元素有一个识别器(比如跟着一个#),那么:target会对使用这个ID识别器的元素增加样式。
:enabled
:disabled
:checked
:not
25.正则验证邮箱
由于邮箱的基本格式为“名称@域名”,需要使用“^”匹配邮箱的开始部分,用“$”匹配邮箱结束部分以保证邮箱前后不能有其他字符,所以最终邮箱的正则表达式为
^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
26.标准模式与怪异模式下盒子模型的计算方式
两种模式的区别:
标准模式会被设置的padding撑开,而怪异模式则相当于将盒子的大小固定好,再将内容装入盒子。盒子的大小并不会被padding所撑开。
标准模式:盒子总宽度/高度 = 设置宽度/高度+padding+border。
怪异模式:盒子总宽度/高度= 内容宽度/高度 + padding + border + margin;
27.你用到了es6中哪些新特性
默认参数
模版表达式
箭头函数
Promise
块级作用域的let和const
模块化
28.描述一个闭包
function A(){
var x = 1;
return function(){
return ++x;
}
}
1.存在一个函数A
2.在函数A内部返回一个函数
3.返回的函数引用A函数的私有变量
4.这个返回的函数是A函数的闭包函数
29.一个箭头函数,如何获取传入的所有实参
用无限参数
var fn = (…args)=>{
console.log(args);
}
这样就可以打印传入的所有参数
注意:在箭头函数中不能使用arguments
30.通讯协议知道哪些?讲讲websocket协议。
http、https、websocket、tcp/ip
webSocket是H5的新协议,它先通过http请求的tcp层3次握手建立连接,然后通过请求带的update:webSocket信息将http协议转换成webSocket协议,再然后就可以服务端向客户端推送信息了。Websocket建立的是长连接,它是双工通信,允许服务器端主动推送信息到客户端。http建立的是短连接,无状态单工通信。
*请认真填写需求信息,我们会在24小时内与您取得联系。