- js中数据类型有哪些?
答:Number(数字类型)、String(字符串类型)、Boolean(布尔类型)、Null(空对象)、undefined、Object
- 以下结果是什么
var str01='123abc';
alert(typeof str01++)
alert(str01)
答:number,NaN。那出现这两个的原因是什么呢?在执行typeof str01++的时候,这个++运算符会偷偷的将我们的str01转成number类型。这是因为在这个过程中++运算符内部会隐式的调用Number()进行类型转换。这个过程我们是看不见的。所以把这一类称之为隐式类型转换。除了++运算符之外还有--,- +(加号比较特殊,也可以转字符类型) * /这些运算符。那还有> < == !==这些运算符和isNaN()会隐式的转换成Boolean类型。还有一种是显示类型转换,常见的就是Number(),String(),Boolean(),parseInt()这些方法。
第二个NaN是为什么呢?因为str01这个字符串既包含了数字也有字母。在执行++操作的时候因为字母的影响结果会是非数字,js中NaN代表非数字,非常特殊。他和任何东西都不等,包括他自己。如果把是str01=‘123’,那么其结果就是先转换成数字类型123,在自增一,结果是数字类型的 124。
- 以下输出的结果是什么?
var a=10;
function test(){
console.log(a);
var a=20;
console.log(a);
}
test()
答:第一个console(a)的结果是undefined;第二个console(a)是20。这是因为var关键字声明的变量会有声明提升现象。它会将声明提升到当前作用域最顶端。在本题中也就是提升到test函数作用域的最顶端。相当于下面的样子。
var a=10;
function test(){
var a;//声明提升至当前作用域最顶端
console.log(a);//undefined
a=20;//变量赋值操作
console.log(a)//20
}
test()
alert(function(){})的结果是?
答:function说一说px,em,rem的区别?
答:px(像素)
px单位的名称为像素,它是一个固定大小的单元,像素的计算是针对(电脑/手机)屏幕的,一个像素(1px)就是(电脑/手机)屏幕上的一个点,即屏幕分辨率的最小分割。由于它是固定大小的单位,单独用它来设计的网页,如果适应大屏幕(电脑),在小屏幕(手机)上就会很不友好,做不到自适应的效果。
em(相对长度单位)
em是相对长度单位,它是用来设置文本的字体尺寸的,它是相对于当前对象内文本的字体尺寸;一般浏览器默认1em=16px,通过设置font-size大小来代表。em是相对于父级元素的单位,会随父级元素的属性(font-size或其它属性)变化而变化。
rem(css3新增的相对长度单位)
rem是css3新增的一个相对长度单位,它的出现是为了解决em的缺点,em可以说是相对于父级元素的字体大小,当父级元素字体大小改变时,又得重新计算。rem出现就可以解决这样的问题,rem只相对于根目录,即HTML元素。所以只要在html标签上设置字体大小,文档中的字体大小都会以此为参照标准,一般用于自适应布局。
rem是相对于根目录(HTML元素)的,所有它会随HTML元素的属性(font-size)变化而变化.
6.如何让一个不确定宽高的元素在水平垂直方向居中。至少说出三种方式
答:通过定位和transform属性来实现。看代码
第一种方法:
HTML
<div class="method01">
<div class="children">方法1:通过定位和transform来实现元素的水平垂直居中</div>
</div>
CSS
<style>
.method01{
width:100%;
height:400px;
background:blue;
position:relative;
}
.children{
position:absolute;
top:50%;
left:50%;
background:red;
transform:translate(-50%,-50%);
}
</style
第二种方法:通过flex弹性布局,给元素父级元素添加display:flex属性
HTML
<div class="method02">
<div class="children">水平垂直居中方法2:通过flex布局来实现</div>
</div>
CSS
<style>
.method02{
width:100%;
height:400px;
background:blue;
display:flex;
align-items:center;
justify-content:center;
}
.children{
background:red;
}
</style>
第三种:设置table属性
HTML
<div class="method03">
<div class="children">元素垂直水平居中方式三,将父元素设置为table,子元素设置为table-cell,利用table属性</div>
</div>
CSS
<style>
.method03{
display:table;
width:100%;
height:400px;
background:blue;
}
.children{
display:table-cell;
vertical-align:middle;
text-align:center;
background:red;
}
</style>
7.说一说this的使用:
- 构造函数中使用。看代码
// 如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象
function Person(){
this.name='张三';
this.age=28;
console.log(this);//person{name: "张三", age: 28}
}
var f1=new Person();
console.log(f1.name);//'张三'
console.log(f1.age);//28
// 如果直接调用Person函数,this是window
- 用call或者apply调用,看代码
// 当一个函数被call或是apply调用时,this的值就取传入的对象的值
var obj={
a:10
};
var func=function(){
console.log(this);//Object {a: 10}
console.log(this.a);//10
}
func.call(obj);
- 最常见的普通函数的调用。看代码
// 在全局环境下,this永远是window
console.log(this===window);//true
// 普通函数在调用时,其中的this也都是window
var a=10;
function test(){
console.log(this);//window
console.log(this.a);//10
}
test();//相当于 window.test()
- cookies,sessionStorage 和 localStorage 的区别.
答:cookies==>
- cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据 -
一般是经过加密的 - cookie数据始终在同源的http请求中携带,每次都会在浏览器和服务器间来回传递。
- sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
- 大小只有4kb。可设置有效时间。
sessionStorage==> - sessionStorage:数据在当前浏览器窗口关闭后自动删除。会话级别。
localStorage==> - 持久存储,浏览器关闭后数据不丢失除非主动删除数据。大小在5M左右。
- 除了ajax你还了解其他实现前后端通信技术吗?
答:Websockets,Fetch。
10.vue中的父子组件是怎么通信的。
答:见代码
父组件
<template>
<div class="parent">
我是父组件
<!--父组件监听子组件触发的say方法,调用自己的parentSay方法-->
<!--通过:msg将父组件的数据传递给子组件-->
<children :msg="msg" @say="parentSay"></children>
</div>
</template>
<script>
import Children from './children.vue'
export default {
// 引入子组件
components:{
children: Children
},
data () {
return {
msg: 'hello, children'
}
},
methods: {
// 参数就是子组件传递出来的数据
parentSay(msg){
console.log(msg) // hello, parent
}
},
}
</script>
子组件
<template>
<div class="hello">
<div class="children" @click="say">
我是子组件
<div>
父组件对我说:{{msg}}
</div>
</div>
</div>
</template>
<script>
export default {
//父组件通过props属性传递进来的数据
props: {
msg: {
type: String,
default: () => {
return ''
}
}
},
data () {
return {
childrenSay: 'hello, parent'
}
},
methods: {
// 子组件通过emit方法触发父组件中定义好的函数,从而将子组件中的数据传递给父组件
say(){
this.$emit('say' , this.childrenSay);
}
}
}
</script>
兄弟组件之间可以使用vuex或者编写一个中间件。
11.vue中数据绑定原理。
答:vue中采用了数据劫持和发布者-订阅者模式。通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。就必须要实现以下几点:
1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm入口函数,整合以上三者
一共分四步, 每一步都有大堆解释和一大堆的代码, 然而我真的只是一个名副其实的理工科生, 看到了文中的发布者-订阅者模式, 于是乎我去网上各种百度, 个人理解就是getter函数里面执行的任务就是watcher订阅者, 而setter函数执行的任务就是发布者; 相信很多人看过了这个也是一知半解, 下面我来解释一波:
ECMAScript中有两种属性: 数据属性和访问器属性, 数据属性一般用于存储数据数值, 访问器属性对应的是set/get操作, 不能直接存储数据值, 每种属性下面又都含有四个特性.下面介绍一下:
数据属性
1.[[Configurable]]: 表示能否通过delete将属性删除,能否把属性修改为访问器属性, 默认为false。当把属性Configurable设置为false后,该属性不能通过delete删除,并且也无法再将该属性的Configurable设置回true
2.[[Enumerable]]: 表示属性可否被枚举(即是否可以通过for in循环返回),默认false
3.[[Writable]]: 表示属性是否可写(即是否可以修改属性的值),默认false
4.[[Value]]: 该属性的数据值, 默认是undefined
访问器属性
1.[[Configurable]]: 表示能否通过delete将属性删除,能否把属性修改为数据属性, 默认为false。当把属性Configurable设置为false后,该属性不能通过delete删除,并且也无法再将该属性的Configurable设置回true
2.[[Enumerable]]: 表示属性可否被枚举(即是否可以通过for in循环返回),默认false
3.[[Get]]: 读取属性时调用的函数, 默认为undefined
4.[[Set]]: 写入属性时调用的函数, 默认是undefined
在修改属性的特性或者定义访问器属性的时候, 需要借助ECMAScript 5中的一个方法: Object.defineProperty(), 这个方法接收三个参数: 属性所在对象, 属性的名字, 描述符对象; 为对象定义多个属性的话, 就用函数的复数写法:Object.defineProperties();
那么通过这个ES5的方法就可以直接很简单粗暴的说明双向绑定的原理:
<input type="text" id="inp" />
<div id="box"></div>
<script>
let obj = {};
let oInp = document.getElementById('inp');
let oBox = document.getElementById('box');
Object.defineProperty(obj, 'name', {
configurable: true,
enumerable: true,
get: function() {
console.log(111)
return val;
},
set: function(newVal) {
oInp.value = newVal;
oBox.innerHTML = newVal;
}
});
oInp.addEventListener('input', function(e) {
obj.name = e.target.value;
});
obj.name = '苏日俪格';
那么实现数据双向绑定的核心就是利用为每一个属性都创建了订阅者的实例对象, 以便观察, getter函数里面返回一个value值,在setter函数中写入修改后的值并调用update方法更新视图的数据值, Configurable和Enumerable这两个特性描述符默认是true, 因此不用写
function defineReactive (obj, key, val) {
var dep = new Dep(); //这是一个构造函数 其原型是为属性添加订阅者
Object.defineProperty(obj, key, {
get: function() {
if(Dep.target) {
dep.addSub(Dep.target); //添加订阅者到Dep实例对象
}
return val; // 返回监听到的value值
},
set: function (newVal) {
if(newVal === val) return;
val = newVal; // 写入新的value值
dep.notify(); // 作为发布者发出通知 然后dep会迭代调用各自的update方法来更新视图
}
});
}
function observe(obj, vm) {
Object.keys(obj).forEach(function(key) {
defineReactive(vm, key, obj[key]);
});
}
转载于苏日俪格链接:https://www.jianshu.com/p/23180880d3aa
简化版vue双向绑定demo地址。https://gitee.com/zhangxiaoniu007/vue_learning_notes