ES6+javaScript原型

Symbol

屬性私有化,數據保護javascript

let _gender = Symbol('gender')

function Person(name, gender) {
    this.name = name;
    this[_gender] = gender
}

Person.prototype.say = function () {
    console.log(this[_gender]);
}
p1.say()

let

不支持變量聲明預解析(先聲明後使用)html

支持塊做用域前端

不容許重複聲明(暫存死區)java

定義的變量不會給window增長屬性node

let c; "c" in window //falsechrome

const

不支持變量聲明預解析(先聲明後使用)數組

支持塊做用域promise

不容許重複聲明(暫存死區)緩存

常量(值一旦肯定,不容許修改,全部必須初始化)數據結構

事件委託

<button class="active">選項一</button>
<button>選項二</button>
<button>選項三</button>
<p class="active">內容一</p>
<p>內容二</p>
<p>內容三</p>
<script>
    var buttons = document.querySelectorAll('button')
    var ps = document.querySelectorAll('p')
    for (let i = 0; i < buttons.length; i++) {
        buttons[i].onclick = function () {
            for (let i = 0; i < buttons.length; i++) {
                buttons[i].className = '';
                ps[i].className = '';
            }
            this.className = 'active';
            ps[i].className = 'active';
        }
    }
<script>

解構賦值

let [a,b,c]=[1,2,3]
let {left:L,top:T}={left:100,top:200}
let [a]='miaov'

擴展運算符

...
    let a = [1, 2, 3, 4];
    console.log(...a);
    console.log(Math.max(...a));
    let b = ['a', 'c', 'v'];
    console.log([...a, 'skd', ...b]);
    let obj1 = {left: 100, right: 200};
    let obj2 = {top: 200, height: 200}
    let obj3 = {
        ...obj1,
        ...obj2
    };
    console.log(obj3);

字符串擴展

\u{1F602} unicode 表示法

``

${表達式}

進制

二進制 0b

八進制 0o(ES6以前:0開頭表示八進制)

十進制 非0開頭

十六進制 0x

迭代

for... in: 以原始插入的順序迭代對象的可枚舉屬性

for... of 根據迭代對象的迭代器具體實現迭代對象數據

let arr = ['a', 'b', 'c'];
for (let string of arr) {
    console.log(string);
}

箭頭函數

//當參數只有一個的時候小括號能夠省略
    let fn = (x) => {
        console.log('fn1')
    };
    let fn = x => {
        console.log('fn1')
    }; 
   //若是多於1條語句,或者返回的是一個對象
    let fn = x => {
        return {
            x: 1,
            y: 2
        }
    };
    箭頭函數的this在函數建立件就綁定好了,箭頭函數的this指向建立該做用域的對象
    箭頭函數的注意事項
    內部this對象指向建立上下文對象
    不能做用構造函數
    沒有arguments
    不能做爲生成器函數
    let obj8={
    name:'zfpx',
    getName:()=>{
        console.log(this.name);
        },
    };
    console.log(obj8.getName());// undefined
    //箭頭函數的this是定死的,指向外層的this

class Person {
        //類
        constructor(name) {//構造函數: 對象初始化的時候執行的函數
            this.name = name
        }

        getName() {
            console.log(this);
        }
    }

    // 繼承
    class Student extends Person {
        constructor(name, type) {
            //super
            super(name);
            //若是子類須要有本身的初始化過程,
            // 有本身的constructor函數,須要在子類調用父類的構造函數
            this.type = type;
        }
    }

promise

避免回調地獄(就是回調嵌套回調無限嵌套)
 接受一個參數:callback,咱們把要執行的異步任務放置在這個callback中

                Promise對象內部會維護一個狀態
                    默認是:pending
                    成功:resolved
                    失敗:rejected

 Promise對象下有一個方法:then,該方法在Promise對象的狀態發生改變的時候觸發then的回調
 catch
     let p1 = new Promise((resolove, reject) => {
        setTimeout(function () {
            resolove(2)
        }, Math.random() * 1000)
    })
    let p2 = new Promise((resolove, reject) => {
        setTimeout(function () {
            resolove(3)
        }, Math.random() * 1000)
    })
    Promise.all([p1, p2]).then(data => {
        console.log(data);
    }, err => {
        console.log(err);
    })

迭代器

yield* 後面跟的是可遍歷的結構,它會調用該結構的遍歷器接口
 function* fn() {
        console.log(0);
        yield console.log(1);
        yield* [1,3,4];
        yield console.log(2);
    }

    //返回一個迭代器函數
    let f = fn();
    f.next()
    f.next()

代碼規範(這一大推寫着寫着就變成這樣了)

在let和const之間優先使用const
儘管const聲明的變量不能直接修改值,可是對於對象和數組,倒是不受保護能夠修改的

靜態代碼一概使用單引號或者反引號

解構
const [a,b]=1,2
cosnt {first,last}=obj

對象
單行定義的對象最後不以逗號結尾
多行定義的對象最後以逗號結尾
const a = { k1: v1, k2: v2 };
const b = {
  k1: v1,
  k2: v2,
};

對象儘可能靜態化
cosnt a={x:null}
a.x=3

對象的屬性和方法簡寫
// bad
const atom = {
  ref: ref,

  value: 1,

  addValue: function (value) {
    return atom.value + value;
  },
};

// good
const atom = {
  ref,

  value: 1,

  addValue(value) {
    return atom.value + value;
  },
};

數組
const itemsCopy=[...items]

Array.from方法 將相似數組的對象轉爲數組
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);

箭頭函數
[1,2,3].map((x)=>{
    return x*x
})
能夠指定原型
cosnt anObject={y:'y'}
const x={
    __proto__:anObject
}

super()

const anObject = {y: 'y', test: () => 'zoo'};

const x = {
    __proto__: anObject,
    test() {
        return super.test() + 'x'
    }
};
console.log(x.test());

動態屬性
const x = {
  ['a' + '_' + 'b']: 'z'
}
x.a_b //z

reduce 有點難理解
第三個參數能夠是索引,默認給值,能夠給{} ,[]

JSON.stringfiy('第一個參數是序列化的參數',
            '第二個參數是一個函數key,value操做',
            '讓代碼清晰些4至關於4個空格')
JSON.parse() 同樣也具備這個特色

//indexOf 若是找不到返回-1    若是重複返回第一個的索引

箭頭函數
let getTempItem = id => ({ id: id, name: "Temp" });//若是不加括號會報錯
若是不須要返回值 void
let fn = () => void console.log(2);
箭頭函數注意點
    函數體內的this對象,就是定義時所在的對象,而不是使用所在的對象
    不能夠看成構造函數,就是說不能new
    箭頭函數沒有本身的做用域
    不可使用arguments
    不可使用yield
    也就是說,this對象的指向是可變的,可是在箭頭函數中,this的指向是固定的
    由於箭頭函數沒有this ,若是真的須要this須要重寫定義this
    function foo() {
      var _this = this;

      setTimeout(function () {
        console.log('id:', _this.id);
      }, 100);
    }
    箭頭函數裏面根本沒有本身的this,而是應用外層的this
    箭頭函數是的this從動態變成靜態,全部須要引用動態this的時候不要使用箭頭函數
Array.from
能夠將各類值轉爲真正的數組,而且還提供map功能
Array.from({ length: 2 }, () => 'jack') //[ 'jack', 'jack' ]
Array.of
用於將一組值,轉換爲數組
Array.of(3, 11, 8) // [3,11,8]
好比  Array(3)//[,,,]  一個值得時候表示的是數組的長度
Array.of   至關於 [].slice.call(arguments)
n**m   指數運算符
雙冒號運算符    取代call   apply  bind
f::b
等同於 b.bind(f);   b.apply(f,arguments);
find
找到第一個複合條件的數組,參數是一個回調函數,返回第一個返回值爲true的成員
[1,2,3,4,5,6].find(a=>a>3) //4
entries()  Object.keys() Object.values()
entries() 對鍵值對遍歷  keys() 對鍵名遍歷  values() 對鍵值遍歷
includes  用於表示數組是否包含特定的值  第二個參數是起始位置默認爲0
[1,3,4].includes(3,2)  //false
對象的擴展   
    const rest = (a, b) => ({a, b});
    console.log(rest('張三', '李四'));
   // { a: '張三', b: '李四' }
   let a = {
    fun () {
        return 'leo';
        }
    }
    // 等同於
    let a = {
        fun : function(){
            return 'leo';
        }
    }   
Object.assign()
深拷貝須要使用其餘方法,由於Object.assign() 拷貝的是屬性值,
假如原對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值
  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  合併對象,合併屬性的時候後續參數中具備相同屬性的覆蓋
    var o1 = { a: 1 };
    var o2 = { b: 2 };
    var o3 = { c: 3 };

    var obj = Object.assign(o1, o2, o3);
    console.log(obj); // { a: 1, b: 2, c: 3 }   
Set
數據結構  全部成員惟一性  add  添加新成員  size  成員總數    delete   has  clear
Map
提供了"值-值"的對應關係,是一種更完善的hash結構實現   set  get  size   has  delete clear

for... of
當遇到next返回值得done屬性爲true就會終止,return 返回的不包括在for...of 循環中
function * f(){
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    return 5;
}
for (let k of f()){
    console.log(k);
}
// 1 2 3 4  沒有 5 

當變量值爲null時,布爾值環境爲false ,值類型爲0
當變量值爲undefined,布爾值環境爲false,值類型爲NaN

ES6開始所有變量和頂層對象(window)的屬性是分開的
let b = 'leo';
window.b; // undefined

字面量
簡單理解就是變量賦值是右邊的都是字面量
let a='hi len'
`hi len` 爲字符串字面量  a爲變量名
var n=1;//字面量建立方式
var num=new Number(1); //構造函數建立方式
閉包
閉包的函數繼承了父級容器的參數和變量,內部函數包含外部函數的做用域
內容函數只能在外部函數中訪問
內部函數造成閉包:能夠訪問外部函數的參數和變量,
但外部函數卻不能使用這個內部函數的參數和變量
外部函數的返回值爲內部函數名

function f(a) {
    function g(b){
        return a + b;
    }
    return g;
}

//默認參數  剩餘參數  
function f(a,b=1,...c) {
    
}


Proxy???

正則

正則  gi   g全局i區分大小寫
exec
注意分組的參數
若檢索成功,返回匹配的數組,不然返回null
let result = /len/g.exec('hello len!!');

//[ 'len', index: 6, input: 'hello len!!' ]
test
若匹配成功返回true不然返回false
let str = "hello leo!";
let res = /leo/.test(str);   // true

search
若檢索成功,返回第一個與正則對象匹配的字符串的起始位置,不然返回-1
let str = "hello leo!";
let res = str.search(/leo/g);  // 6

match
若檢索成功,返回與reg匹配的全部結果的一個數組,不然返回null
str.match(regSS)

Object.defineProperty

定義新屬性或者修改原有的屬性
let obj={
    test: 'hello'
};
//對象已有的屬性添加特性
Object.defineProperty(obj,'test',{
    value:"張三",
    writable:true,//屬性的值是否能夠被重寫,設置爲true能夠被重寫
    enumerable:false,//屬性是否能夠被枚舉(for...in或者object.keys())
    configurable:true,
    //目標屬性是否可使用delete刪除,目標屬性是否能夠再次設置特性
});
//定義的新屬性,特性中configurable,enumerable,writable都爲默認的false
//當使用get或者set方法,不容許使用writable和value這兩個屬性
var obj = {};
Object.defineProperty(obj,"newKey",{
    get:function (){} | undefined,
    set:function (value){} | undefined,
    configurable: true | false,
    enumerable: true | false,
});
//getter 得到屬性值的方法,setter設置屬性值的方法
//get或者set不是必須成對出現的,任寫一個就能夠

ES6

this的調用

var f = function () {
  console.log(this.x);
}

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 單獨執行
f() // 1

// obj 環境執行
obj.f() // 2

this指向問題

javaScript的祕密花園

hasOwnProperty函數
        爲了判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性
        惟一一個處理屬性可是一查找原型鏈上的函數
        使用外部的hasOwnProperty函數獲取正確的結果
        Object.hasOwnProperty.call(foo,'bar')//指向的對象,屬性->返回true,false
    this是基於原型賴以生存的土壤

解構賦值

let obj1={name:'張三', age: 4};
let {name:myname,age:myage}=obj1;
// let myname=obj1.name
// let myage=obj1.age
console.log(myname);
//默認解構
let obj2={name:'zfpx', age: 9};
let {name,age=8}=obj2;
console.log(name, age);

模板字符串的實現原理

function replaces(dec) {
    return dec.replace(/\$\{([^}]+)\}/g,function (arguments,key) {
        console.log(arguments);
        console.log(eval(key));
    })
}
eval()
能夠執行一段javascript 語句
var str = "if (x == 5) {alert('z is 42'); z = 42;} else z = 0; ";
var str1="1+4";
返回值是最後的結果

賦值

  • 基礎數據類型:賦值,賦值以後兩個變量互不影響
  • 引用數據類型: 賦址,兩個變量具備相同的引用,指向同一個對象,相互影響
對於基本類型進行賦值操做,兩個變量互不影響
let a='alex';
let b=a;
a='alex02';
console.log(a);//alex02
console.log(b);//alex
//對於引用類型
let a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let b = a;
b.name="張三";

淺拷貝

* object.assign()  //若是說它是深拷貝是不許確的
用於將全部可枚舉屬性的值從一個或者多個源對象賦值到目標對象
let a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let b = Object.assign({}, a);
console.log(b);
* 展開語法   ...
* Array.prototype.slice() 

let a = [0, "1", [2, 3]];
let b = a.slice(1);
console.log(b);
// ["1", [2, 3]]

a[1] = "99";
a[2][0] = 4;
console.log(a);
// [0, "99", [4, 3]]

console.log(b);
//  ["1", [4, 3]]
淺拷貝:第一層爲基礎數據類型不會是原數據一同改變,
可是原數據子對象會發現改變

深拷貝

JSON.stringify()
JSON.parse()
都不會發生改變
在遇到函數、 undefined 或者 symbol 的時候,該對象也不能正常的序列化

let a = {
    age: undefined,
    sex: Symbol('male'),
    jobs: function() {},
    name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}
你會發如今上述狀況中,該方法會忽略掉函數和 undefined和symbol
可使用lodash中的cloneDeep或者使用30s中的deepClone

new

* 訪問構造函數裏的屬性
* 訪問到原型裏的屬性
注意 不能使用new Symbol();由於Symbol是基本數據類型,每一個Symbol()返回的symbol值都是惟一的
第一種狀況
實例中只能返回返回對象中的屬性
    function Car(color, name) {
        this.color = color;
        return {
            name: name
        }
    }

    var car = new Car("black", "BMW");
    car.color;
    // undefined
第二種狀況
沒有return 返回undefined
且 實例只能訪問構造函數中的屬性
function Car(color, name) {
    this.color = color;
}

var car = new Car("black", "BMW");
car.color;
// black

car.name;
// undefined
總結
* 建立了一個全新的對象
* 這個對象會被執行__proto__連接
* 生成的新對象會綁定到函數調用的this
* 經過new 建立的每一個對象將最終被__proto__ 連接到這個函數的prototype對象上

求和函數sum,使輸入sum(2)(3)或輸入sum(2,3)

函數柯里化
多個參數的函數換成接受一個單一參數
用閉包把參數保存起來,當參數的數量足夠執行函數了,就開始執行函數
let curry=(fn,...args)=>{
    fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args);
};

function sum() {
    if (arguments.length === 1) {
        let sum01=arguments[0];
        let add=function (arg) {
            sum01+=arg;
            return add
        };
        add.valueOf=function () {
            return sum01
        };
        return add;
    }else{
        let sum3=0;
        for (let i = 0; i < arguments.length; i++) {
            sum3+=arguments[i];
        }
        return sum3;
    }
}

console.log(sum(1)(2));
//toString   valueOf均可以

你不知道的Chrome調試工具技巧

控制檯上
$0 是當前選中的html  $1 是咱們上一次選擇的節點的應用...一直到$4
---
Array.from(document.querySelectorAll('dic'))===$$('div')
--
$_  上一次執行的結果的引用
--
控制檯右鍵點擊save  以文件的形式查看錯誤信息
+ '123'            // 123
+ 'ds'               // NaN
+ ''                    // 0
+ null              // 0
+ undefined    // NaN
Boolean過濾數組中的全部假值
雙位操做符替換Math.floor()  可是負數來講就不相同了
~~4.9
取整 |0
返回多行語句 須要用()包裹起來
clas=dir=>(
    Math.PI* diameer;
 )

bind()

bind方法與call/apply最大的不一樣是前端返回一個綁定上下文的函數,後兩個直接執行函數
        var value = 2;

        var foo = {
            value: 1
        };

        function bar(name, age) {
            return {
                value: this.value,
                name: name,
                age: age
            }
        };

        bar.call(foo, "Jack", 20); // 直接執行了函數
        // {value: 1, name: "Jack", age: 20}

        var bindFoo1 = bar.bind(foo, "Jack", 20); // 返回一個函數
        bindFoo1();
        // {value: 1, name: "Jack", age: 20}
能夠指定this 
返回一個函數
能夠傳入參數
柯里化

this存在的問題
        var nickname = "Kitty";
        function Person(name){
            this.nickname = name;
            this.distractedGreeting = function() {

                setTimeout(function(){
                    console.log("Hello, my name is " + this.nickname);
                }, 500);
            }
        }

        var person = new Person('jawil');
        person.distractedGreeting();
        //Hello, my name is Kitty
解決方案1: 緩存this

    var nickname = "Kitty";
    function Person(name){
        this.nickname = name;
        this.distractedGreeting = function() {

            var self = this; // added
            setTimeout(function(){
                console.log("Hello, my name is " + self.nickname); // changed
            }, 500);
        }
    }

    var person = new Person('jawil');
    person.distractedGreeting();
    // Hello, my name is jawil
第二種bind
    var nickname = "Kitty";
    function Person(name){
        this.nickname = name;
        this.distractedGreeting = function() {

            setTimeout(function(){
                console.log("Hello, my name is " + this.nickname);
            }.bind(this), 500);
        }
    }

    var person = new Person('jawil');
    person.distractedGreeting();
    // Hello, my name is jawil
驗證是不是數組
        var toStr = Function.prototype.call.bind(Object.prototype.toString);
        function isArray(obj){ 
            return toStr(obj) === '[object Array]';
        }
        isArray([1, 2, 3]);
        // true

        // 使用改造後的 toStr
        toStr([1, 2, 3]);   // "[object Array]"
        toStr("123");       // "[object String]"
        toStr(123);         // "[object Number]"
        toStr(Object(123)); // "[object Number]"
柯里化

    只傳遞給函數一部分參數來調用,讓它返回一個函數去處理剩下的參數
    var add=function(x){
        return function(y){
            return x+y
        }
    }
    var increment=add(1);
    increment(2)
    這裏定義一個add函數,它接受一個參數並返回一個新的函數,調用add以後,返回的函數
    就經過閉包的方法記住add的第一個參數,全部bind自己也是閉包的一種使用場景
this問題
一個綁定函數也能使用new操做符建立對象,這種就想把原函數當成構造函數
提供的this被忽略,同時調用時的參數被提供給模擬函數
        var value = 2;
        var foo = {
            value: 1
        };
        function bar(name, age) {
            this.habit = 'shopping';
            console.log(this.value);
            console.log(name);
            console.log(age);
        }
        bar.prototype.friend = 'kevin';

        var bindFoo = bar.bind(foo, 'Jack');
        var obj = new bindFoo(20);
        // undefined
        // Jack
        // 20

        console.log(obj.habit);
        // shopping

        console.log(obj.friend);
        // kevin

Array.prototype.slice.call()

將函數的實際參數轉換成數組
Array.prototype.slice.call(arguments)
[].slice.call(arguments,0)  //默認從0開始日後截取
Array.from()  //ES6

防止抖動

會遇到一些頻繁的事件觸發好比:
window: resize,scroll, mousedown mousermove keyup keydown...
當持續觸發事件是,必定時間內沒有再觸發事件,處理函數纔會執行一次
//第一個參數是函數,第二個參數是定時器的時間
function debounce(func, wait) {
    var timeOut;

    return function () {
        if(timeOut) {
            clearTimeout(timeOut);
        }
        // 保存this上下文,參數
        var that = this, args = arguments; //event的問題
        timeOut = setTimeout(function () {
            func.apply(that, args);
        }, wait)
    }
}

toString和valueOf

toString(): 返回對象的字符串表示
valueOf(): 返回對象的字符串,數值或者布爾值表示 
//先看看toString()方法的結果
var a = 3;
var b = '3';
var c = true;
var d = {test:'123',example:123}
var e = function(){console.log('example');}
var f = ['test','example'];

a.toString();// "3"
b.toString();// "3"
c.toString();// "true"
d.toString();// "[object Object]"
e.toString();// "function (){console.log('example');}"
f.toString();// "test,example"

//再看看valueOf()方法的結果
var a = 3;
var b = '3';
var c = true;
var d = {test:'123',example:123}
var e = function(){console.log('example');}
var f = ['test','example'];

a.valueOf();// 3
b.valueOf();// "3"
c.valueOf();// true
d.valueOf();// {test:'123',example:123}
e.valueOf();// function(){console.log('example');}
f.valueOf();// ['test','example']
特殊的地方 表示對象的時候,toString->  [object Object]
而valueOf 返回自身

//例子一
var example = {test:'123'};
console.log(+example);// NaN

//例子二 同時改寫 toString 和 valueOf 方法
var example = {
    toString:function(){
        return '23';
    },
    valueOf:function(){
        return '32';
    }
};
console.log(+example);// 32
經過例子一和例子二中,在有一元加操做符,會先調用valueOf,再調用Number()

節流

無論操做多頻繁,我始終固定時間觸發一次
function throttle(func,wait) {
    let timeout;
    return function () {
        let context=this;
        let args=arguments;
        if(!timeout){
            timeout=setTimeout(function () {
                timeout=null;
                func.apply(context,args);
            },wait)
        }
    }
}

數組去重

function uniq(array){
    var temp = []; //一個新的臨時數組
    for(var i = 0; i < array.length; i++){
        if(temp.indexOf(array[i]) == -1){
            temp.push(array[i]);
        }
    }
    return temp;
}

//filter 第一個參數迭代的對象 第二個是下標,第三個數組自己
array.filter((item, index, array) => array.indexOf(item)===index);

Array.from(new Set(array))

//排序去重
array.concat().sort((a,b)=>a-b)).filter((item,index,array)=>{
//a||b,a爲true返回a
//a&&b,a爲true返回b
    return !index||item!==array[index-1]
})

[...new Set(array")]

類型判斷

typeof  檢測六種基礎類型+object+function
Undefined null Boolean String number Symbol  function Object
Object.prototype.toString.call(obj)=> [object 類型]

最大值最小值

Maxs=arr=>{
    let res=arr[0];
    for(let i=0;i<arr.length;i++){
        res=Math.max(res,arr[i]);
    }
    return res;
}

Math.max.apply(null,arr)

Math.max(...arr)

arr.reduce((r, v) => Math.max(r, v)))

arr.sort((a,b)=>b-a)[0]

arr.reduce((r,v)=r>v?r:v)

數組扁平化

flatten=arr=>arr.reduce((r,s)=>{
    return r.concat(Array.isArray(s)?flatten(s):s)
},[])

flatten=arr=>arr.toString().split(',').map(item=>Number(item));

flatten=arr=>arr.join('.').split(',').map(item=>parseInt(item));

flatten=arr=>{
    let res=[];
    return arr.map(item=>{
        return arr.isArray(item)?res=res.concat(flatten(item)):res.push(item);
    })
}

//some至少有一個
function flatten(arr) {
    while(arr.some(item=>Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}

//Array.from  toString   split

在數組中查找指定索引

indexOf
//ES6
findIndex   返回符合條件的第一個元素的索引
findLastIndex  倒序

深刻理解javascript

數組是對象,函數是對象,對象仍是對象,對象裏面的一切都是屬性,只有屬性,沒有方法,方法也是屬性

一切(引用類型)都是對象,對象是屬性的集合

null是js中一個基本數據類型,之因此顯示"Object",是由於對象在底層被表示爲二進制,在js中中二進制前三位爲0會被判斷爲object類型,null的二進制都是0,天然前三位也是0,因此返回對象

對象都是經過函數建立的

function Fn() {
            this.name = '王福朋';
            this.year = 1988;
        }
        var fn1 = new Fn();
        //var obj = { a: 10, b: 20 };  語法糖
        //var arr = [5, 'x', true];      語法糖

        var obj = new Object();
        obj.a = 10;
        obj.b = 20;

        var arr = new Array();
        arr[0] = 5;
        arr[1] = 'x';
        arr[2] = true;

其中Object 和Array都是函數

console.log(typeof (Object));  // function
console.log(typeof (Array));  // function

prototype原型

Fn.Prototype.constructor=Fn

隱式原型__proto__

每一個函數function都有一個prototype,每一個對象都有一個__proto__

obj.__proto__===Object.prototype

實例出來的對象都有一個__proto__屬性,指向建立這個對象的函數的prototype

可是Object.prototype是一個特例,它的__proto__指向的是null

函數也是一種對象,函數也有__proto__嗎?

function fn(x,y){
    return x+y;
}
var fn1=new Function('x','y','return x+y;')
第一種是傳統的函數建立方式,第二種是new Function建立的,
第二種不推薦
----

fn.__proto__===Fuction.prototype

對象的__proto__指向建立它的函數的prototype

Object.__proto__=== Function.prototype
var a = Function.prototype; //將Function.prototype看做一個基本對象a,此時:
a.constructor === Function;
a.__proto__.constructor === Object; //a.__proto__指向Object.pototype

instanceof 是作類型檢測的
"abc" instanceof String  //false  左邊不是Object類型直接返回false
"abc".__proto__ instanceof  String.prototype

instanceof判斷規則是

沿着A 的__proto__ 這條線來找,若是B的prototype在這條線上,那麼返回true,不然返回false

function Foo(){}
    var f1 = new Foo();
    console.log(f1 instanceof Foo); // true
    console.log(f1 instanceof Object); // true
     
    分析方法:
        f1的__proto__路線A:
            (1) f1.__proto__ === Foo.prototype
            (2) Foo.prototype.__proto__ === Object.prototype
            (3) Object.prototype.__proto__ === null //到終點

Object函數也是Fucntion建立出來的,並且Fucntion是被自身建立的

訪問一個對象的屬性時,先在基本屬性中查找,若是沒有,再沿__proto__這條鏈往上找

執行上下文環境或者叫執行上下文,

  • 變量,函數表達式---變量聲明默認爲undefined
  • this
  • 函數聲明

你不知道的javascript

把類數組轉換成真正的數組

  • Array.prototype.slice.call(arguments)
  • Array.from(arguments)

判斷對象是什麼引用類型

  • Object.prototype.toString.call(obj)

toNumber()

  • 基本類型值true=1,false=0,undefined=NaN,null=0,處理失敗返回NaN
  • 若是有valueOf方法先進行強制轉換,若沒有則用toString進行強制轉換

toBoolean()

  • 假值:undefined ,null,false,+0,-0,NaN," ",假值之外都是真值

取整

  • ~~ 取整,負數向上取整,正數向下取整
  • x|0 也能夠取整,規則同上

強制轉換成Boolean

  • !!

==

  • NaN不等於NaN,+0不等於-0
  • null==undefined,由於null,undefined是假值轉化爲boolean值都是0
  • 下面通常狀況下爲true
"0" == false //隱式轉化
false == 0    
false == "" 
false == [] //[]的length爲0=>array(0)  []爲0
"" == 0
"" == []
0 ==[]
  • 若是兩邊的值中有[],"",0 儘可能不要用==,兩邊有true和false也不要用==

{}+[]

  • {} 被看成一個獨立的空代碼塊,+[]強制類型轉換爲0

[]+{}

  • []會轉換爲"" ,+{}後,會強制轉換爲"[object object]"

優先級

  • &&>||>?> :

函數會首先被提高,而後纔是變量

console.log(a);//因爲上面已聲明a,相同的變量名聲明會被直接忽略掉
// [Function a]
var a = "孫悟空";
function a(){ console.log("小鑽風"); }

var a=1;
var a;
console.log(a);//1

自執行函數不會進行變量提高的

等號右邊沒有變量提高的

console.log(ff);//ff is not defiend
var f= funciton ff(){}

無論條件是否成立都要變量提高,可是var和function聲明不定義,當條件成立第一步先給函數賦值

console.log(a); //undefined
console.log(F); //undefined
if(true){
    var a=1;
    function F() {
        
    }
}
//----------------
f=function(){return true}
g=function(){return false}
(function(){
    if(g()&&[]==![]){ //g=undefined  ,g()會報錯,已經條件判斷,只聲明不定義
        f=function f(){return false}
        function g(){return true}
    }
})

發佈訂閱者模式

沒理解

引用數據類型

let obj={a: 1};// b:xxxFFFF111
let obj1=obj;
obj1.b=obj={x: 1};
console.log(obj.b);// undefined
console.log(obj1.b);//{x:1}

function fn() {
    this.name = '張三';
}

console.log(fn.name); //fn

console.log((new Function('res', 'return res')).name);//anonymous

function fn3(y,x='你好',z) {

}
//函數的length是形參的長度,可是默認值不算在裏面,並且書寫規範,默認值應該寫在最後,
//若是默認值等於return, 後續不會執行,會影響默認值
console.log(fn3.length);//1

//函數聲明
num()//報錯
var num = function (){
    console.log(1);
}

私有做用域

var a=1;
var b=2;
function AA(a){
    a++; //NaN
    b++; //3
    console.log(a); //NaN
    console.log(b); //3
}
AA()
console.log(a); //1
console.log(b); //3

-----
var a=3;
function B(a,b) {
    a++;
    console.log(a + b); //7
}
B(a,a++); a++因爲是後++ ,全部傳入給b依然是3
console.log(a); a=4

//----------------------------
var code=null;
function fn1(n) {
    n=n||code++; //n=0
    return ++code; //code =2
}
var n=fn1();//2
console.log(n);//2
//---------------
n=f2(m);
var m=0;
function f2(n){
    n=isNaN(n);//isNaN(undefined)==>true
    return n;
}
console.log(window.n)

//------
var ary = [1, 2, 3];

function FF(ary) {
    ary.push(100);
    ary.shift();
    ary = ary[ary.length - 1];
    return ary;
}

console.log(FF(ary));//100
console.log(ary);//[ 2, 3, 100 ]
相關文章
相關標籤/搜索