变量类型和计算知识点:
值类型、引用类型
//值类型
var a=100
var b=a
a=200
console.log(b) //100
//引用类型
var a={age:20}
var b=a
b.age=21
console.log(a.age) //21
typeof
// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写
typeof Number(1) === 'number'; // 但不要使用这种形式!
// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof总是返回一个字符串
typeof String("abc") === 'string'; // 但不要使用这种形式!
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 但不要使用这种形式!
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';
// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined';
// Objects
typeof {a:1} === 'object';
// 使用Array.isArray 或者 Object.prototype.toString.call
// 区分数组,普通对象
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
// 下面的容易令人迷惑,不要使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) ==== 'object';
typeof new String("abc") === 'object';
// 函数
typeof function(){} === 'function';
typeof Math.sin === 'function';
//NaN
typeof 1/0 === 'NaN';
//null
typeof null === 'object';
强制类型转换
//逻辑运算符
console.log(10 & 0) //0 转换为true&&0
console.log(''||'abc') //abc 转换为false||'abc'
console.log(!window.abc) //true !undefined为true
//if语句 false情况
null '' false 0 NaN undefined
//判断一个变量是否当作true或者false
var a = 100
console.log(!!a)
面试题:
1.JS中使用typeof能得到哪些类型
undefined null string number object function boolean symbol
2.何时使用'===',何时使用'=='
参考jQuery源码 只有这种情况下使用'==':
if(obj.a == null) {
}
//这句相当于obj.a === null || obj.a === undefined
3.JS有哪些内置函数
Object Array String Number Function Boolean Date RegExp Error
4.JS变量按照存储方式分为哪些类型,并描述其特点
值类型、引用类型。
值类型是将变量的值存在内存中。
引用类型的变量是真实变量的指针(对象、数组、函数)。可以无限扩张属性。
5.如何理解JSON
是JavaScript的对象,内置两个方法 JSON.stringify JSON.parse
原型知识点:
构造函数
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this 默认有这行
}
var f = new Foo('zs', 20)
//执行过程:1.new函数执行时this会变成空对象 2.this. 的时候赋值 3.return this 4.给f赋值
//var a = {} ===> var a = new Object()
//var a =[] ===> var a = new Array()
//function Foo(){} ===> var Foo = new Function()
//instanceof 用于判断一个函数是否是一个变量的构造函数
原型规则
//所有的引用类型(数组、对象、函数)都具有对象特性,除了null之外,都可以自由扩展属性
//所有的引用类型 都有__proto__ 隐式原型
//所有的函数都有 prototype 显式原型 属性值也是一个普通对象
//所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的prototype属性值
var obj = {}; obj.a = 100
var arr = []; arr.a = 100
function fn () {}
fn.a = 100
console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)
console.log(fn.prototype)
console.log(obj.__proto__ === Object.prototype)
//试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(构造函数的prototype)中寻找
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
var f = new Foo('zs')
f.printName = function () {
console.log(this.name)
}
f.printName()
f.alertName()
原型链 instanceof
//instanceof 是用于判断引用类型属于哪个构造函数的方法
//构造函数
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
//创建实例
var f = new Foo('zs')
f.printName = function () {
console.log(this.name)
}
f.printName()
f.alertName()
f.toString()
// f instanceof Foo 判断过程:
// f 的 __proto__一层层往上找到是否对应Foo.prototype
// 再判断f instanceof Object
直角矩形是构造函数 圆角矩形是对象
hasOwnProperty
var obj={
x:100,
y:200,
z:300
}
var key
for(key in obj){
//hasOwnProperty会返回一个布尔值,判断是否是原生的属性,以此来排除原型链上的属性
if(obj.hasOwnProperty(key)){
console.log(key,obj[key]);
}
}
//x 100
//y 200
//z 300
面试题
6.如何准确判断一个变量是数组函数
var arr = []
arr instanceof Array
typeof arr //object, typeof 是无法判断是否是数组的
7.写一个原型链继承的例子
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('wrapper')
div1.html('<p>hello</p>').on('click', function () {
alert('clicked')
}).html('<p>javascript</p>')
8.描述new一个对象的过程
//创建一个对象
//this指向这个对象
//执行代码 即对this赋值
//返回this
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this 构造函数最好不要写return
}
var f = new Foo('zs', 20)
作用域和闭包知识点:
执行上下文
//执行上下文:当前被执行代码的环境/作用域
console.log(a)
var a = 100
fn('zs')
//函数声明
function fn(name) {
console.log(this)
console.log(arguments)
age = 20
console.log(name, age)
var age
bar(100)
function bar(num) {
console.log(num)
}
}
//函数表达式: var fn = function () {}
//在全局代码执行前,会将变量定义和函数声明先提出来
//在函数代码执行前,会将变量定义,函数声明,this,arguments(所有参数的集合)先提出来
this
//this的值执行时才能确定
var a = {
name: 'A',
fn: function () {
console.log(this.name) //这个阶段的this无法确定值
}
}
a.fn() //this === a
a.fn.call({name: 'B'}) //this === {name: 'B'}
var fn1 = a.fn
fn1() //this === window
//作为构造函数执行
function Foo(name) {
// this = {}
this.name = name
// return this
}
var f = new Foo('zs')
//作为对象属性执行
var obj = {
name: 'A',
printName: function () {
console.log(this.name) //这里this就是obj
}
}
obj.printName
//作为普通函数执行
function fn() {
console.log(this) //这里的this就是window
}
fn
//call apply bind
function fn1(name, age) {
console.log(name)
console.log(this) //这里的this是{x:100}
}
fn1.call({x:100}, 'zs', 20)
var fn2h = function fn2(name, age) {
console.log(name)
console.log(this) //这里的this是{y:200}
}.bind({y:200})
fn2('zs', 20)
作用域 作用域链
//不断向父级作用域寻找变量的过程形成了作用域链
//没有块级作用域概念
if (true) {
var name = 'zs'
}
console.log(name)
//函数、全局作用域
var a = 10
function fn() {
var a = 200
console.log('fn', a)
}
console.log('global', a)
fn()
var b = 100
function fn() {
var c = 200
console.log(b) //当前作用域没有定义的变量叫做自由变量
console.log(c)
}
fn()
var a = 100
function f1() {
var b = 200
function f2() {
var c = 300
console.log(a)
console.log(b)
console.log(c)
}
f2()
}
f1()
//哪个作用域定义了f1这个函数,f1的父级作用域就是谁
闭包
//闭包应用:1.函数作为返回值
function F1() {
var a = 100
//返回一个函数
return function () {
console.log(a) //100
}
}
//f1得到一个函数
var f1 = F1()
var a = 200
f1()
//2.函数作为参数传递
function F1() {
var a = 100
return function() {
console.log(a) //100
}
}
var f1 = F1()
function F2(fn) {
var a = 200
fn()
}
F2(f1)
面试题
9.说一下对变量提升的理解
变量定义、函数声明会提前。
10.说明this几种不同的使用场景
作为构造函数、对象属性、普通函数执行,call apply bind
11.创建10个<a>
标签,点击时弹出对应序号
var i
for (i = 0; i < 10; i++) {
(function (i) {
var a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
12.如何理解作用域
自由变量、作用域链,即自由变量的寻找、闭包的两个场景。
13.实际开发中闭包的应用
封装变量,收敛权限 案例:
function isFirstLoad() {
var _list = []
return function (id) {
if (_list.indexOf(id) >=0) {
return false
} else {
_list.push(id)
return true
}
}
}
var firstLoad = isFirstLoad()
console.log(firstLoad(10))
console.log(firstLoad(10))
console.log(firstLoad(20))
console.log(firstLoad(20))
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。