JS创建对象对象的方法
1)new一个Object的实例 实例化一个Object对其添加属性和方法,把实例保存在变量person中
var person = new Object();
person.name="zj";
person.age=20;
person.say = function(){
alert("hi")
}
2)对象字面量模式
var person = {
name:"zj";
age:"20";
say : function(){
alert(this.name);
}
}
前两种方法都是用了同一个接口创建很多对象,会产生大量的重复代码
3)工厂模式
function createPerson(name,age,jpb){
var p = new Object();
p.name = name;
p.age = age;
p.job = job;
p.say = function(){
alter(this.name);
}
return p;
}
var p1 = createPerson('NCT',18,'singer');
var p2 = createPerson('RV',22,'dancer');
解决了一个一个的创建对象问题,没有解决对象识别问题(怎么知道一个对象的类型)返回的都是Object类型。
4)构造函数模式
function Person(name,age,jpb){
this.name = name;
this.age = age;
this.jpb = jpb;
this.say = function(){
alert(this.name)
}
}
var person1 =new Person('NCT',18,'singer');
var person2 =new Person('RV',22,'dancer');
对比工厂模式的区别:
- 没有显示地创建对象
- 直接将属性和方法赋给了this对象
- 没有return语句
- 可以识别对象的类型使用instanceof操作符
alert(person1 instanceof Object);//ture alert(person1 instanceof Person);//ture alert(person2 instanceof Object);//ture alert(person2 instanceof Object);//ture
缺点: 每个方法都要在每个实例上重新创建一遍,方法指的是在对象里定义的函数,如果方法数量很多就会占用很多不必要的内存。
5)原型创建对象模式
function Person() {
}
Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
alert(this.name);
};
console.log(Person.prototype);
var person1 = new Person();
console.log(person1.name);
var person2 = new Person();
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2);
console.log(person2.age);
function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name ='Greg';
alert(person1.name);
alert(person2.name);
所有对象实例共享它的属性和方法 当为对象实例添加一个属性的时候,这个属性就会屏蔽原型对象中保存的同名属性。
6)组合使用构造函数和原型模式 构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。
function Person(name,age,job){
this.name =name;
this.age = age;
this.job = job;
}
Person.prototype = {
constructor:Person,
sayName: function(){
alert(this.name);
};
}
var person1 = new Person('Nike',20,'teacher');
组合模式共享对相同方法的引用,也保证了每个实例有自己的私有属性,最大限度节省了内存。
JS有哪些数据类型
基本数据类型:Null、Undefined、String、Number、Boolean、Object、Symbol、BigInt(ES6新增) Symbol:表示创建后独一无二且不可变的数据类型,主要是解决可能出现的全部变量冲突问题。 BigInt:数字类型的数据,表示任意精度格式的整数。超过Number表示的安全数范围也可以。
引用数据类型:Object、Array、Date、Function、RegExp
栈:原始数据类型 堆:引用数据类型(对象、数据、函数)
JS数据类型判断方法
1)typeof 其中数组、对象、null都会被判断为object,其他的判断都正确
console.log(typeof 2);
console.log(typeof true);
console.log(typeof 'str');
console.log(typeof []);
console.log(typeof function(){});
console.log(typeof {});
console.log(typeof undefined);
console.log(typeof null);
2)instanceof 可以正确判断对象的引用数据类型,不能判断基本数据类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。
console.log(2 instanceof Number);
console.log(true instanceof Boolean);
console.log('str' instanceof String);
console.log([] instanceof Array);
console.log(function(){} instanceof Function);
console.log({} instanceof Object);
3)constructor
console.log((2).constructor === Number);
console.log((true).constructor === Boolean);
console.log(('str').constructor === String);
console.log(([]).constructor === Array);
console.log((function() {}).constructor === Function);
console.log(({}).constructor === Object);
如果创建了一个对象改变了它的原型,constructor就不能用来判断数据类型了。
function Fn(){};
Fn.prototype = new Array();
var f = new Fn();
console.log(f.constructor===Fn);
console.log(f.constructor===Array);
4)Object.protype.toString.call() 使用Object对象的原型方法toString来判断数据类型
console.log(Object.prototype.toString.call(undefined));
console.log(Object.prototype.toString.call(null));
console.log(Object.prototype.toString.call(123));
console.log(Object.prototype.toString.call("abc"));
console.log(Object.prototype.toString.call(true));
function fn() {
console.log("ming");
}
var date = new Date();
var arr = [1, 2, 3];
var reg = /[hbc]at/gi;
console.log(Object.prototype.toString.call(fn));
console.log(Object.prototype.toString.call(date));
console.log(Object.prototype.toString.call(arr));
console.log(Object.prototype.toString.call(reg));
同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?
这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。
instanceof 操作符的实现原理以及实现
instanceof运算符用于判断构造函数的prototype属性是否出现在对象的原型链中的任何位置。
function myInstanceof(left,right){
let proto = Object.getPrototype(left)
let prototype = right.prototype;
while(true){
if( !proto )
return false;
if( proto === prototype )
return true;
proto = Object.getPrototype(proto);
}
}
HTML5有哪些更新
1)语义化标签
- header:定义文档的页面(头部)
- nav:定义导航链接的部分
- footer:定义文档或节的页脚(底部)
- article:定义文章的内容
- section:定义文档中的节
- aside:定义其所处内容之外的内容(侧边)
2)媒体标签 - audio:音频
- video:视频
- source:在video指定视频源
3)表单 表单类型 - email:验证邮箱地址是否合法
- url:验证URL
- number:只能输入数字,可以设置max/min/value默认值
- search:输入框后会给提供一个小叉,可以删除输入的内容
- color:提供一个颜色拾取器
- time:时分秒
- data:日期选择年月日
- datatime:时间和日期(目前只有safari支持)
- datatime-local:日期时间控件
表单属性:
- placeholder:提示信息
- autofocus:自动获取焦点
- autocomplete=“on“ 或者 ”off“ 使用前提(表单必须提交过、必须有name属性)
- required:要求输入框不能为空,有值才能提交。
- pattern = “ ” 里面写入想要的正则模式,例如手机号"^(+86)?\d{10}$"
- multiple:可以选择多个文件或者邮箱
- form = “from表单的ID”
表单事件:
- oninput:每当input里的输入框内容发生变化都会触发此事件
- oninvalid:验证不通过时触发此事件
4)DOM查询操作
- document.querySelector()
- document.querySelectorAll()
它们选择的对象可以是标签,可以是类(需要加点),可以是ID(需要加#)
5)web存储 localStorage、sessionStorage
CSS3中有哪些新特性
边框: border-radius:添加圆角边框 border-shadow:给框添加阴影(水平位移,垂直位移,模糊半径,阴影尺寸,阴影颜色,insetr[内/外部阴影]) border-image:设置边框图像 bode-image-source:边框图片的路径 boder-image-repeat:图像边框是否平铺(repeat平铺 round铺满 stretch拉伸) 背景: background-size:背景图片尺寸 background-origin:规定background-position属性相对于什么位置定位。 background-clip:规定背景的绘制区域(padding-box,border-box,content-box) 渐变: linear-break:定义如何换行 word-wrap:允许长的内容可以自动换行 text-overflow:当文本溢出包含他的元素时应该干啥 text-shadow:文字阴影(水平位移,垂直位移,模糊半径,阴影颜色) 转换: transform应用于2D3D转换,可以将元素旋转、移动 缩放、倾斜 transform-origin:可以更改元素转换的位置(xyz轴) transform-style:指定嵌套元素怎么样在三位空间中呈现 2D转换方法: rotate旋转translate(x,y)指定元素在二维空间的位移scale(n)定义缩放转换 3D转换方法: perspective(n)为3D转换translate rotate scale 过渡: transition-property过去属性名 transition-duration:完成过渡效果需要花费的时间 transition-timing-function:指定切换效果的速度 transition-delay:指定什么时候开始切换效果 动画: animation-name 为@keyframes动画名称 animation-duration 动画需要花费的时间 animation-timing-function 动画如何完成一个周期 animation-delay 动画启动前的延迟间隔 animation-iteration-count 动画播放次数 animation-direction 是否轮流反向播放动画
vue生命周期
beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy destroyed
vue组件传值
父传子 父组件需要把数据绑定:名称 = 值 绑定上去 子组件通过props 接收
子传父 子组件通过$emit 传自定义事件 父组件接收
兄弟传值 公共事件bus $emit 传自定义事件 $on 进行接收
Vue的基本原理
当一个vue实例创建是,vue会遍历data中的属性,用Object.defineProperty(vue3使用proxy)将他们转为getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。每个组件实例都用相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用的时候,会通知watcher重新计算,从而致使它关联的组件得以更新。
MVC和MVVM的区别
MVC MVC通过分离Model、View和Controller的方式来组织代码结构。View负责页面显示逻辑,Model负责存储页面的业务数据、以及对应的数据操作。View和Model应用了观察者模式,当Model层发生改变的时候会通知有关View层更新页面。Controller层是View和Model的纽带,主要负责用户与应用的响应操作,当用户与页面产生交互的时候,Controller中的事件触发器就开始工作了,通过调用Model层来完成对Model的修改,然后Model层再去通知View层更新。 MVVM Model代表数据模型,数据和业务逻辑都在Model层中定义 View代表UI视图,负责数据的展示 ViewModel负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作。
Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Mode中同步。 这种模式实现了Model和View的数据自动同步,因此开发者只需要专注于数据的维护操作即可,而不需要自己操作DOM
computed和Watch的区别
computed计算属性:不支持异步,依赖其他的属性值,并且computed值有缓存,只有它依赖的属性值发生改变,下一次获取computed值的时候才会重新计算computed的值。 watch侦听器:支持异步,更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
computed和methods的区别
computed是基于缓存的,如果计算的属性没有变换是不会重新计算的,执行缓存数据。 methods是没有缓存的,也就是只要调用了就会执行该方法。
v-if和v-show的区别
- v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显示或者隐藏。
- v-if切换有一个局部编译/卸载的过程,切换过程中合适的销毁和重建内部的事件监听和子组件;v-show只是简单的基于css的切换。
- 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做,只有在条件第一次为真的时候才编译;v-show是在任何条件下,无论真假都被编译,任何被缓存,而且DOM元素保留。
- v-if有更高的切换消耗;v-show有更高的初始渲染消耗。
- v-if适合运营条件不大可能改变;v-show适合频繁的切换。
data为什么是一个函数而不是对象?
JS中的对象是引用类型的数据,当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化。 而在vue中,更多的是想要复用组件,那就需要每个组件都有自己的数据,这样组件之间才不会互相干扰。 所以组件的数据不能写成对象的形式,而是要写成函数的形式。数据以函数返回值的形式定义,这样当每次复用组件的时候,就会返回一个新的data,每个组价都会有自己的私有数据空间,各自维护自己的数据,不会干扰其他组件的正常运行。
vue-router的懒加载如何实现
非懒加载:
import List from '@/components/list.vue'
const router = new vueRouter({
routes:[{
path:'/list',
component:List
}]
})
1)方法一:使用箭头函数+import动态加载
const List =() => import('@/components/list.vue')
const router = new vueRouter({
routes:[{
path:'/list',
component:List
}]
})
2)方法二:使用箭头函数+require动态加载
const router = new vueRouter({
routes:[{
path:'/list',
component:resolve => import(['@/components/list]',resolve)
}]
})
3)方法三:使用webpack的require.ensure技术,也可以实现按需加载。多个路由指定相同的chunkName,会合并打包成一个js文件。
const List = r => require.ensure([],()=>
r(require('@/components/list')),'list');
const router = new Router({
routes: [
{
path: '/list',
component: List,
name: 'list'
}
]
})
)
|