建设银行网站登录,江苏省建设执业资格中心网站,百度如何快速收录,网站建设的潜在客户img的srcset属性的作⽤#xff1f;
响应式页面中经常用到根据屏幕密度设置不同的图片。这时就用到了 img 标签的srcset属性。srcset属性用于设置不同屏幕密度下#xff0c;img 会自动加载不同的图片。用法如下#xff1a;
img srcimage-128.png srcset
响应式页面中经常用到根据屏幕密度设置不同的图片。这时就用到了 img 标签的srcset属性。srcset属性用于设置不同屏幕密度下img 会自动加载不同的图片。用法如下
img srcimage-128.png srcsetimage-256.png 2x /
使用上面的代码就能实现在屏幕密度为1x的情况下加载image-128.png, 屏幕密度为2x时加载image-256.png。
按照上面的实现不同的屏幕密度都要设置图片地址目前的屏幕密度有1x,2x,3x,4x四种如果每一个图片都设置4张图片加载就会很慢。所以就有了新的srcset标准。代码如下
img srcimage-128.pngsrcsetimage-128.png 128w, image-256.png 256w, image-512.png 512wsizes(max-width: 360px) 340px, 128px /
其中srcset指定图片的地址和对应的图片质量。sizes用来设置图片的尺寸零界点。对于 srcset 中的 w 单位可以理解成图片质量。如果可视区域小于这个质量的值就可以使用。浏览器会自动选择一个最小的可用图片。
sizes语法如下
sizes[media query] [length], [media query] [length] ...
sizes就是指默认显示128px, 如果视区宽度大于360px, 则显示340px。
左右居中方案
行内元素: text-align: center定宽块状元素: 左右 margin 值为 auto不定宽块状元素: table布局position transform
/* 方案1 */
.wrap {text-align: center
}
.center {display: inline;/* or *//* display: inline-block; */
}
/* 方案2 */
.center {width: 100px;margin: 0 auto;
}
/* 方案2 */
.wrap {position: relative;
}
.center {position: absulote;left: 50%;transform: translateX(-50%);
}Loader和Plugin 有什么区别
Loader直译为加载器。Webpack将一切文件视为模块但是webpack原生是只能解析js文件如果想将其他文件也打包的话就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。 Plugin直译为插件。Plugin可以扩展webpack的功能让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件Plugin 可以监听这些事件在合适的时机通过 Webpack 提供的 API 改变输出结果。
什么是 JavaScript 中的包装类型
在 JavaScript 中基本类型是没有属性和方法的但是为了便于操作基本类型的值在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象如
const a abc;
a.length; // 3
a.toUpperCase(); // ABC
在访问abc.length时JavaScript 将abc在后台转换成String(abc)然后再访问其length属性。
JavaScript也可以使用Object函数显式地将基本类型转换为包装类型
var a abc
Object(a) // String {abc}
也可以使用valueOf方法将包装类型倒转成基本类型
var a abc
var b Object(a)
var c b.valueOf() // abc
看看如下代码会打印出什么
var a new Boolean( false );
if (!a) {console.log( Oops ); // never runs
}
答案是什么都不会打印因为虽然包裹的基本类型是false但是false被包裹成包装类型后就成了对象所以其非值为false所以循环体中的内容不会运行。
为什么函数的 arguments 参数是类数组而不是数组如何遍历类数组?
arguments是一个对象它的属性是从 0 开始依次递增的数字还有callee和length等属性与数组相似但是它却没有数组常见的方法属性如forEach, reduce等所以叫它们类数组。
要遍历类数组有三个方法
1将数组的方法应用到类数组上这时候就可以使用call和apply方法如
function foo(){ Array.prototype.forEach.call(arguments, a console.log(a))
}
2使用Array.from方法将类数组转化成数组
function foo(){ const arrArgs Array.from(arguments) arrArgs.forEach(a console.log(a))
}
3使用展开运算符将类数组转化成数组
function foo(){ const arrArgs [...arguments] arrArgs.forEach(a console.log(a))
}
代码输出结果
function runAsync(x) {const p new Promise(r setTimeout(() r(x, console.log(x)), 1000));return p;
}
function runReject(x) {const p new Promise((res, rej) setTimeout(() rej(Error: ${x}, console.log(x)), 1000 * x));return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)]).then(res console.log(result: , res)).catch(err console.log(err));
输出结果如下
0
Error: 0
1
2
3
可以看到在catch捕获到第一个错误之后后面的代码还不执行不过不会再被捕获了。
注意all和race传入的数组中如果有会抛出异常的异步任务那么只有最先抛出的错误会被捕获并且是被then的第二个参数或者后面的catch捕获但并不会影响数组中其它的异步任务的执行。
参考 前端进阶面试题详细解答
事件是什么事件模型
事件是用户操作网页时发生的交互动作比如 click/move 事件除了用户触发的动作外还可以是文档加载窗口滚动和大小调整。事件被封装成一个 event 对象包含了该事件发生时的所有相关信息 event 的属性以及可以对事件进行的操作 event 的方法。
事件是用户操作网页时发生的交互动作或者网页本身的一些操作现代浏览器一共有三种事件模型
DOM0 级事件模型这种模型不会传播所以没有事件流的概念但是现在有的浏览器支持以冒泡的方式实现它可以在网页中直接定义监听函数也可以通过 js 属性来指定监听函数。所有浏览器都兼容这种方式。直接在dom对象上注册事件名称就是DOM0写法。IE 事件模型在该事件模型中一次事件共有两个过程事件处理阶段和事件冒泡阶段。事件处理阶段会首先执行目标元素绑定的监听事件。然后是事件冒泡阶段冒泡指的是事件从目标元素冒泡到 document依次检查经过的节点是否绑定了事件监听函数如果有则执行。这种模型通过attachEvent 来添加监听函数可以添加多个监听函数会按顺序依次执行。DOM2 级事件模型在该事件模型中一次事件共有三个过程第一个过程是事件捕获阶段。捕获指的是事件从 document 一直向下传播到目标元素依次检查经过的节点是否绑定了事件监听函数如果有则执行。后面两个阶段和 IE 事件模型的两个阶段相同。这种事件模型事件绑定的函数是addEventListener其中第三个参数可以指定事件是否在捕获阶段执行。 操作符的强制类型转换规则
对于 来说如果对比双方的类型不一样就会进行类型转换。假如对比 x 和 y 是否相同就会进行如下判断流程
首先会判断两者类型是否**相同**相同的话就比较两者的大小类型不相同的话就会进行类型转换会先判断是否在对比 null 和 undefined是的话就会返回 true判断两者类型是否为 string 和 number是的话就会将字符串转换为 number
1 1↓
1 1
判断其中一方是否为 boolean是的话就会把 boolean 转为 number 再进行判断
1 true↓
1 1↓1 1
判断其中一方是否为 object 且另一方为 string、number 或者 symbol是的话就会把 object 转为原始类型再进行判断
1 { name: js } ↓1 [object Object]
原型修改、重写
function Person(name) {this.name name
}
// 修改原型
Person.prototype.getName function() {}
var p new Person(hello)
console.log(p.__proto__ Person.prototype) // true
console.log(p.__proto__ p.constructor.prototype) // true
// 重写原型
Person.prototype {getName: function() {}
}
var p new Person(hello)
console.log(p.__proto__ Person.prototype) // true
console.log(p.__proto__ p.constructor.prototype) // false
可以看到修改原型的时候p的构造函数不是指向Person了因为直接给Person的原型对象直接用对象赋值时它的构造函数指向的了根构造函数Object所以这时候p.constructor Object 而不是p.constructor Person。要想成立就要用constructor指回来
Person.prototype {getName: function() {}
}
var p new Person(hello)
p.constructor Person
console.log(p.__proto__ Person.prototype) // true
console.log(p.__proto__ p.constructor.prototype) // true
对 rest 参数的理解
扩展运算符被用在函数形参上时它还可以把一个分离的参数序列整合成一个数组
function mutiple(...args) {let result 1;for (var val of args) {result * val;}return result;
}
mutiple(1, 2, 3, 4) // 24
这里传入 mutiple 的是四个分离的参数但是如果在 mutiple 函数里尝试输出 args 的值会发现它是一个数组
function mutiple(...args) {console.log(args)
}
mutiple(1, 2, 3, 4) // [1, 2, 3, 4]
这就是 … rest运算符的又一层威力了它可以把函数的多个入参收敛进一个数组里。这一点经常用于获取函数的多余参数或者像上面这样处理函数参数个数不确定的情况。
JS 整数是怎么表示的
通过 Number 类型来表示遵循 IEEE754 标准通过 64 位来表示一个数字1 11 52最大安全数字是 Math.pow(2, 53) - 1对于 16 位十进制。符号位 指数位 小数部分有效位
代码输出结果
function runAsync (x) {const p new Promise(r setTimeout(() r(x, console.log(x)), 1000))return p
}
function runReject (x) {const p new Promise((res, rej) setTimeout(() rej(Error: ${x}, console.log(x)), 1000 * x))return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]).then(res console.log(res)).catch(err console.log(err))
输出结果如下
// 1s后输出
1
3
// 2s后输出
2
Error: 2
// 4s后输出
4
可以看到。catch捕获到了第一个错误在这道题目中最先的错误就是runReject(2)的结果。如果一组异步操作中有一个异常都不会进入.then()的第一个回调函数参数中。会被.then()的第二个回调函数捕获。
new操作符的实现原理
new操作符的执行过程
1首先创建了一个新的空对象
2设置原型将对象的原型设置为函数的 prototype 对象。
3让函数的 this 指向这个对象执行构造函数的代码为这个新对象添加属性
4判断函数的返回值类型如果是值类型返回创建的对象。如果是引用类型就返回这个引用类型的对象。
具体实现
function objectFactory() {let newObject null;let constructor Array.prototype.shift.call(arguments);let result null;// 判断参数是否是一个函数if (typeof constructor ! function) {console.error(type error);return;}// 新建一个空对象对象的原型为构造函数的 prototype 对象newObject Object.create(constructor.prototype);// 将 this 指向新建对象并执行函数result constructor.apply(newObject, arguments);// 判断返回对象let flag result (typeof result object || typeof result function);// 判断返回结果return flag ? result : newObject;
}
// 使用方法
objectFactory(构造函数, 初始化参数);
常见的DOM操作有哪些
1DOM 节点的获取
DOM 节点的获取的API及使用
getElementById // 按照 id 查询
getElementsByTagName // 按照标签名查询
getElementsByClassName // 按照类名查询
querySelectorAll // 按照 css 选择器查询// 按照 id 查询
var imooc document.getElementById(imooc) // 查询到 id 为 imooc 的元素
// 按照标签名查询
var pList document.getElementsByTagName(p) // 查询到标签为 p 的集合
console.log(divList.length)
console.log(divList[0])
// 按照类名查询
var moocList document.getElementsByClassName(mooc) // 查询到类名为 mooc 的集合
// 按照 css 选择器查询
var pList document.querySelectorAll(.mooc) // 查询到类名为 mooc 的集合
2DOM 节点的创建
创建一个新节点并把它添加到指定节点的后面。 已知的 HTML 结构如下
htmlheadtitleDEMO/title/headbodydiv idcontainer h1 idtitle我是标题/h1/div /body
/html
要求添加一个有内容的 span 节点到 id 为 title 的节点后面做法就是
// 首先获取父节点
var container document.getElementById(container)
// 创建新节点
var targetSpan document.createElement(span)
// 设置 span 节点的内容
targetSpan.innerHTML hello world
// 把新创建的元素塞进父节点里去
container.appendChild(targetSpan)
3DOM 节点的删除
删除指定的 DOM 节点 已知的 HTML 结构如下
htmlheadtitleDEMO/title/headbodydiv idcontainer h1 idtitle我是标题/h1/div /body
/html
需要删除 id 为 title 的元素做法是
// 获取目标元素的父元素
var container document.getElementById(container)
// 获取目标元素
var targetNode document.getElementById(title)
// 删除目标元素
container.removeChild(targetNode)
或者通过子节点数组来完成删除
// 获取目标元素的父元素var container document.getElementById(container)// 获取目标元素var targetNode container.childNodes[1]// 删除目标元素container.removeChild(targetNode)
4修改 DOM 元素
修改 DOM 元素这个动作可以分很多维度比如说移动 DOM 元素的位置修改 DOM 元素的属性等。
将指定的两个 DOM 元素交换位置 已知的 HTML 结构如下
htmlheadtitleDEMO/title/headbodydiv idcontainer h1 idtitle我是标题/h1p idcontent我是内容/p/div /body
/html
现在需要调换 title 和 content 的位置可以考虑 insertBefore 或者 appendChild
// 获取父元素
var container document.getElementById(container) // 获取两个需要被交换的元素
var title document.getElementById(title)
var content document.getElementById(content)
// 交换两个元素把 content 置于 title 前面
container.insertBefore(content, title)
Promise.resolve
Promise.resolve function(value) {// 1.如果 value 参数是一个 Promise 对象则原封不动返回该对象if(value instanceof Promise) return value;// 2.如果 value 参数是一个具有 then 方法的对象则将这个对象转为 Promise 对象并立即执行它的then方法if(typeof value object then in value) {return new Promise((resolve, reject) {value.then(resolve, reject);});}// 3.否则返回一个新的 Promise 对象状态为 fulfilledreturn new Promise(resolve resolve(value));
}
JavaScript有哪些内置对象
全局的对象 global objects 或称标准内置对象不要和 “全局对象global object” 混淆。这里说的全局的对象是说在 全局作用域里的对象。全局作用域中的其他对象可以由用户的脚本创建或由宿主程序提供。
标准内置对象的分类
1值属性这些全局属性返回一个简单值这些值没有自己的属性和方法。例如 Infinity、NaN、undefined、null 字面量
2函数属性全局函数可以直接调用不需要在调用时指定所属对象执行结束后会将结果直接返回给调用者。例如 eval()、parseFloat()、parseInt() 等
3基本对象基本对象是定义或使用其他对象的基础。基本对象包括一般对象、函数对象和错误对象。例如 Object、Function、Boolean、Symbol、Error 等
4数字和日期对象用来表示数字、日期和执行数学计算的对象。例如 Number、Math、Date
5字符串用来表示和操作字符串的对象。例如 String、RegExp
6可索引的集合对象这些对象表示按照索引值来排序的数据集合包括数组和类型数组以及类数组结构的对象。例如 Array
7使用键的集合对象这些集合对象在存储数据时会使用到键支持按照插入顺序来迭代元素。 例如 Map、Set、WeakMap、WeakSet
8矢量集合SIMD 矢量集合中的数据会被组织为一个数据序列。 例如 SIMD 等
9结构化数据这些对象用来表示和操作结构化的缓冲区数据或使用 JSON 编码的数据。例如 JSON 等
10控制抽象对象 例如 Promise、Generator 等
11反射。例如 Reflect、Proxy
12国际化为了支持多语言处理而加入 ECMAScript 的对象。例如 Intl、Intl.Collator 等
13WebAssembly
14其他。例如 arguments
总结 js 中的内置对象主要指的是在程序执行前存在全局作用域里的由 js 定义的一些全局值属性、函数和用来实例化其他对象的构造函数对象。一般经常用到的如全局变量值 NaN、undefined全局函数如 parseInt()、parseFloat() 用来实例化对象的构造函数如 Date、Object 等还有提供数学计算的单体内置对象如 Math 对象。
JavaScript 类数组对象的定义
一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象类数组对象和数组类似但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果还有一个函数也可以被看作是类数组对象因为它含有 length 属性值代表可接收的参数个数。
常见的类数组转换为数组的方法有这样几种
1通过 call 调用数组的 slice 方法来实现转换
Array.prototype.slice.call(arrayLike);
2通过 call 调用数组的 splice 方法来实现转换
Array.prototype.splice.call(arrayLike, 0);
3通过 apply 调用数组的 concat 方法来实现转换
Array.prototype.concat.apply([], arrayLike);
4通过 Array.from 方法来实现转换
Array.from(arrayLike);
对类数组对象的理解如何转化为数组
一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象类数组对象和数组类似但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果函数参数也可以被看作是类数组对象因为它含有 length属性值代表可接收的参数个数。
常见的类数组转换为数组的方法有这样几种
通过 call 调用数组的 slice 方法来实现转换
Array.prototype.slice.call(arrayLike);
通过 call 调用数组的 splice 方法来实现转换
Array.prototype.splice.call(arrayLike, 0);
通过 apply 调用数组的 concat 方法来实现转换
Array.prototype.concat.apply([], arrayLike);
通过 Array.from 方法来实现转换
Array.from(arrayLike);
说一下JSON.stringify有什么缺点
1.如果obj里面有时间对象则JSON.stringify后再JSON.parse的结果时间将只是字符串的形式而不是对象的形式
2.如果obj里有RegExp(正则表达式的缩写)、Error对象则序列化的结果将只得到空对象
3、如果obj里有函数undefined则序列化的结果会把函数或 undefined丢失
4、如果obj里有NaN、Infinity和-Infinity则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性例如 如果obj中的对象是有构造函数生成的 则使用JSON.parse(JSON.stringify(obj))深拷贝后会丢弃对象的constructor
6、如果对象中存在循环引用的情况也无法正确实现深拷贝
CSS预处理器/后处理器是什么为什么要使用它们
预处理器 如lesssassstylus用来预编译sass或者less增加了css代码的复用性。层级mixin 变量循环 函数等对编写以及开发UI组件都极为方便。
后处理器 如 postCss通常是在完成的样式表中根据css规范处理css让其更加有效。目前最常做的是给css属性添加浏览器私有前缀实现跨浏览器兼容性的问题。
css预处理器为css增加一些编程特性无需考虑浏览器的兼容问题可以在CSS中使用变量简单的逻辑程序函数等在编程语言中的一些基本的性能可以让css更加的简洁增加适应性以及可读性可维护性等。
其它css预处理器语言SassScss, Less, Stylus, Turbine, Swithch css, CSS Cacheer, DT Css。
使用原因
结构清晰 便于扩展可以很方便的屏蔽浏览器私有语法的差异可以轻松实现多重继承完美的兼容了CSS代码可以应用到老项目中