1、JS使用typeof能得到哪些类型?
考点: JS变量类型
typeof undefined, //undefined
typeof 'abc' ,//string
typeof 123 ,//number
typeof true ,//boolean
typeof {} ,//object
typeof [] ,//object
typeof null ,//object
typeof console.log ,//function
typeof Symbol(1) // symbol
2、何时使用 === 何时使用 == ?
考点: 强类型转换
if(obj.a == null){
//这里相当于 obj.a === null || obj.a === undefined,简写形式
//这是 jquery 源码中推荐的写法
}
3、JS中有哪些内置函数?
Object、Array、Boolean、Number、String、Function、Date、RegExp、Error、Math、JSON、window、document等。。
4、JS变量按照存储方式区分哪些类型,并描述其特点
//值类型
//占用空间固定,值保存在栈中
//保存与复制的是值本身
var a = 10;
var b = a;
a = 11
console.log(b) //10
//引用类型
//占用空间不固定,值保存在堆中
//保存与复制的是指向对象的一个指针
var obj1 = {x: 100};
var obj2 = obj1;
obj1.x = 200;
console.log(obj2.x) //200
5、如何理解JSON?
JSON 只不过是一个 JS 对象而已
JSON.stringify({a:10, b:20})
JSON.parse('{"a": 10, "b": 20 }')
——链接
值类型(内存中存具体值) vs 引用类型(内存中存的指针)
引用类型:对象,数组,函数
引用类型特点:不限制扩张属性
因为引用类型占据空间较大,所以用指针来共享空间
typeof运算符详解
使用instanceof判断变量的详细类型
使用Object.prototype.toString判断。
强制类型转换(值类型)
字符串拼接
== 运算符
使用 == 的情况,除了以下情况,其他一律用 ===
查看对象的属性是否存在 》if (obj.a == null){ }
查看函数中的参数是否存在 》function(a,b) {if (a == null) {...} }
var obj = {};
if(obj.a == null){
//这里相当于 obj.a === null || obj.a === undefined,简写形式
//这是 jquery 源码中推荐的写法
}
if语句
逻辑运算 (&&、||、!(not))
0、NaN、’’、""、null、undefined、false 自动转换为false
//字符串拼接
var a = 100 + 10 //110
var b = 100 + '10' //"10010"
// == 运算符
100 == '100' //true
0 == '' //true
//if语句
if(100) {} //把数字转换为true
if('') {} //把字符串转换为false
//逻辑运算
console.log(10&&0) //0 把10转换为true
console.log(''||'abc') // "abc" 把‘’转换为false
console.log(!window.abc)//true window.abc是undefined,把非undefined 转换 为true
//判断一个变量会被当做true还是false
var a = 100
console.log(!!a); // true
1、如何准确判断一个变量是数组类型
?
变量 instanceof
Array
var arr = [];
arr instanceof Array //true
typeof arr //"object", typeof 是无法判断是否是数组的
2、写一个原型链继承的例子
//写一个封装DOM的例子
function Elem(id){
this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
var elem = this.elem;
if(val){
elem.innerHTML = val;
return this; //链式操作, 可有可无
}else{
return elem.innerHTML;
}
}
Elem.prototype.on = function(type, fn){
var elem = this.elem;
elem.addEventListener(type, fn);
return this;
}
var div1 = new Elem('div1');
//console.log(div1.html())
div1.html('hello world
'
).on('click', function(){
alert('clicked');
}).html('javascript
'
3、描述 new 一个对象的过程
function Foo(name, age) {
this.name = name
this.age = age
//return this;
}
var f = new Foo('zhangsan', age)
4、zepto(或其他框架)源码中如何使用原型链
//基本碰到首字母大写的函数, 就是构造函数,so构造函数尽量大写字母开头
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this //默认有这一行
}
var f = new Foo('zhangsan', 20)
//var f1 = new Foo('lisi', 22) //创建多个对象
所有的引用类型
(数组、对象、函数),都具有对象的特性、即可自由扩展属性(除了 “null” 意外)
所有的引用类型
(数组、对象、函数),都有一个__proto__
(隐式原型) 属性,属性值是一个普通的对象
所有的函数
,都有一个prototype
(显示原型) 属性, 属性值也是一个普通的对象
所有引用类型
(数组、对象、函数),__proto__
属性值都指向它的构造函数的 prototype
属性值
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__
(即它的构造函数的prototype) 中寻找。
var obj = {}; obj.a = 100; //1
var arr = []; arr.a = 100;
function Fn() {}
Fn.a = 100;
console.log(obj.__proto__);//2
console.log(arr.__proto__);
console.log(Fn.__proto__);
console.log(Fn.prototype);//3
console.log(obj.__proto__ === Object.prototype)//4 5
//构造函数
function Foo(name, age) {
this.name = name;
}
Foo.prototype.alertName = function() {
alert(this.name);
}
//创建示例
var f = new Foo('zhangsan')
f.printName = function() {
console.log(this.name)
}
//无论是函数f自身属性,还是从原型得到的属性,this永远指向f自己本身
f.printName();
f.alertName();
f.toString(); //要去 f.__proto__.__proto__ 寻找
//循环对象自身的属性
var item
//for in 对函数属性进行循环
for (item in f) {
//高级浏览器已经存在 for in 中屏蔽了来自原型的属性
//但是这里建议加上这个判断,保证程序的健壮性
if(f.hasOwnProperty(item)) {
console.log(item)
}
}
JavaScript对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbtUgEGA-1590071179192)(https://i.loli.net/2019/05/21/5ce3f4978a28565863.png)]
instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置
f
instanceof
Foo 的判断逻辑是:f 的
__proto__
一层层往上,能否对应到 Foo.prototype在试着判断 f
instanceof
Object
1、说一下对变量提升的理解
分为变量定义和函数声明(和函数表达式的区别)
全局作用域和函数作用域或者是(ES6)中块级作用域,变量声明(var)和函数声明会被提升到作用域顶部,而函数表达式不会,只是当做一个var变量提升,函数没有被提升,另外ES6 中 let 和 const标识符定义的变量也不会发生提升(暂时性死区 TDZ)
2、说明this几种不同的使用场景
this指的是当前运行的环境,即执行的时候
3、创建10个a标签,点击的时候弹出来对应的序号
var i;
for(i=0, i<10,i++) {
var a = document.createElement('a');
(function(i) {
a.innerHTML= a +'
';
a.addEventListener('click', function(e) {
e.preventDefault();
alert(i)
})
document.body.appendChild(a);
})(i)
}
4、如何理解作用域
5、实际开发中闭包的应用
闭包实际引用中主要用于封装变量,收敛权限
function isFirstLoad() {
var _list = []
return function(id){
if(_list.indexOf(id) >= 0){
return false;
}else {
_list.push(id)
return true
}
}
}
var firstload = isFirstLoad();
firstload(10); //true
firstload(10); //false
firstload(20); //true
范围:一段
全局:变量定义、函数声明
函数:变量定义、函数声明、this、arguments、函数
PS:注意“函数声明”和“函数表达式”的区别
function fn(name) {
//函数 开头默认创建this arguments
console.log(this)
console.log(arguments)
age = 20 //声明提前
console.log(name, age)
var age
bar(100)
function bar(num) {
console.log(num)
}
}
console.log(a)//undefined
var a = 100
fn('zhangsan') //'zhangsan' 20
function fn(name) {
age = 20
console.log(name, age)
var age
}
在全局环境中,this 永远指向 window。
this
要在执行时才能确认值,定义时无法确认
var a = {
name: 'A',
fn: function() {
console.log(this.name)
}
}
a.fn() //this === 'a'
a.fn.call({name: 'B'}) //this === {name: 'B'}
var fn1 = a.fn
fn1() //this === window
作为构造函数执行
作为对象属性执行
作为普通函数执行 (this指向window)
call
apply
bind
function Foo(name) {
this.name = name
}
//由一个函数new出来的对象,this就代表即将new出来的这个对象
var f = new Foo('zhangsan')
var obj = {
name: 'A'
printName: function() {
console.log(this.name)//构造函数中的this
}
}
obj.printName() //对象中的this指向该对象 this === 'A'
function fn() {
console.log(this) //this === window 普通函数中的this永远指向window。
}
fn()
//call apply bind
function fn1(name , age) {
alert(name)
console.log(this)
}
fn1.call({x:100}, 'zhangsan', 20) //常用
fn1.apply({x:100}, ['zhangsan', 20])
//bind 要用函数表达式
var fn2 = function (name, age) {
alert(name)
alert(age)
console.log(this)
}.bind({y: 200}, 'lisi', 11);
fn2('zhangsan', 20)
自由变量不停的往父级作用域查找,就是所谓的作用域链
var a = 100
function F1() {
var b = 200
//当前作用域没有定义的变量,即“自由变量”
function F2() {
console.log(a) // a是自由变量
console.log(b) // b是自由变量
console.log(c)
}
F2()
}
有权访问另一个函数作用域中的变量的函数
函数作为返回值,在父作用域去找自由变量的值
函数作为参数传递
function F1() {
var a = 100
//返回一个函数 (函数作为返回值)
return function() {
console.log(a)
}
}
//f1的得到一个函数
var f1 = F1()
var a = 200
F1()// 打印 100
function F2(fn) { //函数作为参数传递
var a = 200
fn()
}
F2(f1) // 打印 100
什么是异步(对比同步)
setTimeout
,setInverval
console.log('start')
//网络请求
$.get('./data1.json',function(data1) {
console.log(data1)
})
//图片加载
var img= document.createElement('img')
img.onload = function() {
console.log('loaded')
}
img.src = '/xxx.png'
//事件绑定
document.getElementById('btn1').addEventListener('click',function() {
alert('clicked')
})
console.log('end')
获取 2017-06-10格式的日期
function formatDate(dt) {
if(!dt) {
dt = new Date()
}
var year = dt.getFullYear()
var month = dt.getMonth()
var date = dt.getDate()
if(month < 10){
month = '0' + month
}
if(date < 10){
date = '0' + date
}
return year + '-' + month + '-' + date
}
console.log(formatDate(new Date()))
获取随机数,要求是长度一致的字符串格式
var random = Math.random()
random = random + '0000000000';
random = random.slice(0, 10);
console.log(random)
写一个能遍历对象和数组的通用 forEach 函数
function forEach(obj, fn){
var key
if(obj instanceof Array){
obj.forEach(function(item, index) {
fn(index, item)
})
}else {
if(obj.hasOwnProperty(key)){
for(key in obj) {
fn(key, obj[key])
}
}
}
}
var arr = [1,2,3]
forEach(arr, function(index, item) {
console.log(index, item)
})
var obj = {x:100, y:200}
forEach(obj, function(key, val) {
console.log(key, val)
})
Date.now() //获取当前毫秒数
var dt = new Date()
dt.getTime() //获取毫秒数
dt.getFullYear() //年
dt.getMonth() //月 (0 - 11) 要加上 +1
dt.getDate() //日 (0 - 31)
dt.getHours() //小时 (0 - 23)
dt.getMinutes() //分钟 (0 - 59)
dt.getSeconds() //秒 (0 - 59)
Math.random() //获取随机数 在链接后加随机数,可以清除缓存
var arr = [1,2,3]
arr.forEach(function(item, index) {
//遍历数组的所有元素
console.log(index, item)
});
var result1 = arr.every(function(item, index) {
//用来判断所有的数组元素,都满足一个条件
if(item < 4){
return true
}
})
console.log(result1)
var result2 = arr.some(function(item, index) {
//用来判断所有的数组元素,只要有一个满足条件即可
if(item < 2) {
return true
}
})
console.log(result2)
var arr1 = [1,4,2,3,5]
var arr2 = arr1.sort(function(a, b) {
// 从小到大排序
//return a - b
//从大到小排序
return b - a
})
console.log(arr2)
var arr3 = [1,2,3,4]
var arr4 = arr.map(function(item, index) {
//将元素重新组装,并返回
return '' + item +''
})
console.log(arr4)
var arr5 = arr.filter(function (item, index) {
//通过某一个条件过滤数组
if(item >= 2) {
return true
}
})
console.log(arr5)
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for(key in obj){
//注意这里的 hasOwnProperty ,过滤掉原型链中的属性
if(obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
常说的JS(浏览器执行的JS)包含两部分
DOM是哪种基本的数据结构
DOM操作的常用API有哪些
DOM节点的Attribute 和property有和区别
var elem = document.getElementById( 'id' );
//Attribute 添加,删除,获取
elem.getAttribute('gameid')
elem.getAttribute('gameid')
elem.removeAttribute('gameid')
//property 添加,删除,获取
elem.gameid = 880; // 添加
console.log( elem.gameid ) // 获取
delete elem.gameid // 删除
新增节点
var div1 = document.getElementById('div1')
//添加新节点
var p1 = document.createElement('p')
p1.innerHTML = 'this is p1'
div1.appendChild(p1) //添加新创建的元素
//移动已有节点
p2 = document.getElementById('p2')
div1.appendChild('p2')
获取父元素
var div1 = document.getElementById('div1')
var parent = div1.parentElement;
var child = div1.childNodes
div1.removeChild(child[0])
获取子元素
删除节点
var div1 = document.getElementById('div1')//元素
var divList = document.getElementsByTagName('div') //集合
console.log(divList.length)
console.log(divList[0])
var containerList = document.getElementsByClassName('.container')//集合
var plist = document.querySelectorAll('p') //集合
题目
var btn = document.getElementById('btn1')
btn.addEventListener('click', function(event) {
console.log('clicked')
})
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
var a = document.getElementById('link1')
bindEvent(a , 'click', function(e) {
e.preventDefault()//阻止默认行为
alert('clicked')
})
DOM事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。 dom标准事件流的触发的先后顺序为:先捕获再冒泡
//addEventListener最后一个参数,为true则代表使用事件捕获模式,
//false则表示使用事件冒泡模式。即默认模式
window.addEventListener('click', function() {
console.log('4. You click window');
}, true);
关于IE低版本的兼容性
通用事件绑定与解绑
版本管理GIT
JS模块化
打包工具
页面渲染
性能优化
6、window.onload 和 DOMConetentLoaded 的区别?
考点:浏览器渲染过程
7、用JS创建10个标签, 点击的时候弹出来对应的序号?
考点:作用域
8、简述如何实现一个模块加载器, 实现类似require.js的基本功能?
考点:JS模块化
9、实现数组的随机排序?
考点:JS基础算法
同源策略可防止 JavaScript 发起跨域请求。源被定义为 URI、主机名和端口号的组合。此策略可防止页面上的恶意脚本通过该页面的文档对象模型,访问另一个网页上的敏感数据。
原因:浏览器同源策略导致了跨域
作用:隔离恶意文件的重要安全机制
解决: