变量类型
- 值类型和引用类型
- 值类型只能存储一个值
- 值类型复制就是值类型本身
- 引用类型复制只是复制引用类型的指针
- 引用类型:对象,数组,函数
- 引用类型特点:可以无限制的扩展属性
- JS中使用typeof能得到哪些类型:7种类型
- undefined string number boolean symbol object function
- typeof不能详细区分引用类型(对象、数组)的详细类型
- 但是可以详细区分function以及所有值类型。
typeof a//undefined
typeof undefined//undefined
typeof 'abc' //string
typeof 123 //number
typeof NaN //number
typeof true //boolean
typeof {} //object
typeof [] //object
typeof null //object
typeof console.log //function
typeof Symbol('foo') //symbol
变量计算-强制类型转换
- 字符串拼接
let a=100;
let b=10;
console.log(a+b);//110
let a=100;
let b='10';
console.log(a+b);//10010
console.log(a-b);//90
- ==运算符
100=='100'//true
0==''//true(0和''都可以转换成false)
null==undefined//true(null和undefined都可以转换成false)
- if语句
let a=true
if(a){
console.log(a);//true
}
let b=100;
if(b){
console.log(b);//100
}
let c='';
if(c){
console.log('c')
}
//c=''是false,if语句不执行
- 逻辑运算
console.log(10&&0);//0
console.log(''||'abc');//abc
console.log(!window.abc);//true
//判断一个变量会被当做true还是false
var a=100;
console.log(!!a);//true
- 何时使用===,何时使用 ==
//仅有这种情况使用'=='
if(obj.a==null){
//此时条件相当于obj.a===null||obj.a===undefined,简写形式
//这是jQuery源码中推荐的写法
}
除此之外,其它情况均建议使用'==='
- JS有哪些内置函数
- js内置函数是浏览器内核自带的,不用任何函数库引入就可以直接使用的函数。
- Object,Array,Boolean,Number,String,Function,Date,RegExp,Error
- Math是内置对象
- Math内置对象常用方法
- Math.floor():向下取整
- Math.ceil():向上取整
- Math.round():四舍五入
- Math.max(a,b):取a,b之间最大值
- Math.min(a,b):取a,b之间最小值
- Math.random:取0-1之前的随机数
let a=4.3;
console.log(Math.round(a));
console.log(Math.ceil(a));
console.log(Math.floor(a));
console.log(Math.max(5,3));
console.log(Math.min(1,4));
function random(min,max) {
return min+Math.random()*(max-min)
}
console.log(random(1,10));
- JS变量按照存储方式分为哪些类型,并描述其特点
- 值类型和引用类
- 值类型可以将数据分块存储在内存中
- 引用类型是多个变量共用一个内存块,引用类型的赋值是指定了一个指针,并不是真正的值的拷贝,它们之间是会相互干预的。
- 如何理解JSON
- JSON是JS中的一个内置对象
JSON.stringify({a:10,b:20}) //"{"a":10,"b":20}"将对象转换为字符串
JSON.parse('{"a":10,"b":20}') //{a: 10, b: 20}把字符串转换为对象
原型和原型链
- 构造函数
function Foo(name,age) {
this.name=name;
this.age=age;
this.class='class-1';
// return this;//默认有这一行
}
var f=new Foo('wbq',22);
- 构造函数-扩展
var a={};//其实是var a=new Object()的语法糖
var b=[];//其实是var b=new Array()的语法糖
function Foo() {};//其实是var Foo=new Function(){}的语法糖
- 原型规则和示例
- 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了'null')
- 所有的引用类型(数组、对象、函数),都具有proto属性,属性值是一个普通的对象
- 所有的函数,都有一个prototype属性,属性值也是一个普通对象
- 所有的引用类型(数组、对象、函数),proto属性值指向它的构造函数的prototype属性
- 当试图得到一个对象的某个属性时,如果对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找
var obj={};obj.a=100;
var arr=[];arr.a=100;
function fn(){};fn.a=100
console.log(obj.__proto__);//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
console.log(fn.__proto__);//ƒ () { [native code] }
console.log(fn.prototype);//{constructor: ƒ}
console.log(obj.__proto__===Object.prototype);//true
function Foo(name,age) {
this.name=name;
this.age=age;
}
Foo.prototype.alertName=function () {
alert(this.name)
}
var f=new Foo('wbq');
f.printName=function () {
console.log(this.name)
}
f.printName();
f.alertName();
- 循环对象自身的属性方法
- for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
function Foo(name,age) {
this.name=name;
this.age=age;
}
Foo.prototype.alertName=function () {
alert(this.name)
}
var f=new Foo('wbq');
f.printName=function () {
console.log(this.name)
}
f.printName();
f.alertName();
for(let i in f){
console.log(i);//name,age,printName,alertName
}
//如何只遍历对象自身的属性,不遍历继承的可枚举属性
for(let i in f){
if(f.hasOwnProperty(i)){
console.log(i,f[i])
}
}
- Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替。
Object.values(obj):方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
bject.entries():方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
console.log(Object.keys(f));// ["name", "age", "printName"]
let obj={
'name':'wbq',
'age':20,
sayName(){
console.log(this.name)
}
}
console.log(Object.keys(obj));//[ 'name', 'age', 'sayName' ]
console.log(Object.values(obj));//[ 'wbq', 20, [Function: sayName] ]
console.log(Object.entries(obj));
// [ [ 'name', 'wbq' ],
// [ 'age', 20 ],
// [ 'sayName', [Function: sayName] ] ]
- Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
- Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
- Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
- 原型链
如果对象本身没有某个属性,则通过proto向上查找,最终都没有这个属性,则返回null,这种通过proto一级一级向上查找,则形成了原型链
- instanceof
- 用于判断引用类型属性是哪个构造函数的方法
- f instanceof Foo的判断逻辑是:
- f的proto一层一层往上,能否对应到Foo.prototype
- 如何准确判断一个变量是数组类型
var arr=[]
arr instanceof Array //true
typeof arr //object typeof无法准确判断是否是数组
- 写一个原型链继承的例子
function Animal(name){
this.name=name
}
Animal.prototype.run=function(){
console.log('run');
};
function Dog(name) {
Animal.call(this,name)
}
Dog.prototype=new Animal();
let dog=new Dog('wbq');
dog.run();
console.log(dog.name)
- 封装一个DOM查询
ddd
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');
div1.on('click',function () {
alert('click')
}).html('链式操作
')
- 描述new一个对象的过程
//创建一个构造函数
function Foo(name,age){
// this={}
this.name=name
this.age=age
// return this
}
var f=new Foo('wbq',10);
- 创建一个新对象:{}
- 将构造函数的作用域赋给新对象(因此this指向这个新对象):this={}
- 执行构造函数中的代码(为这个新对象添加属性):this.xxx=xxx
- 返回新对象:return this
let newFun=function (func) {
//1.新建一个空对象,并将 构造函数的原型对象赋给这个空对象
let obj=Object.create(func.prototype);
//2.执行构造函数,相应参数被传入,并将this的上下文指向新创建的对象obj
var ret=func.call(obj);
//3.如果构造函数返回了对象,就舍弃之前创建的对象obj,newObj = ret
if(typeof ret === 'object') return ret;
else return obj;
}
var foo = function(name){
this.name = name || 'lalaBao';
}
var newObj = newFun(foo);
console.log(newObj);
作用域和闭包
- 执行上下文
- 范围:一段