變量類型、原型、閉包、做用域面試題及知識點簡單總結

變量類型和計算知識點:

值類型、引用類型

//值類型
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源碼 只有這種狀況下使用'==':javascript

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.parsehtml

原型知識點:

構造函數

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

直角矩形是構造函數 圓角矩形是對象
clipboard.pngjava

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>標籤,點擊時彈出對應序號app

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))
相關文章
相關標籤/搜索