面向?qū)ο缶幊?和 函數(shù) - 復(fù)習(xí)

2018-6-28復(fù)習(xí)
每一次回頭看基礎(chǔ)僚匆,都有新的理解

Function.prototype.call

函數(shù)實(shí)例的call方法,可以指定函數(shù)內(nèi)部this的指向(即:函數(shù)執(zhí)行時(shí)所在的作用域,--- 函數(shù)運(yùn)行時(shí)所在的對(duì)象 )口柳,然后在所指定的作用域中,調(diào)用該函數(shù)。
注意: call方法是函數(shù)的方法
應(yīng)用:

  1. 將 ( 類似數(shù)組的對(duì)象 ) 轉(zhuǎn)換成 ( 數(shù)組 )

(1)
[].slice.call(arguments)
等于 Array.prototype.slice.call(arguments)
等于 Array.from(arguments)
--- [].slice.call(arguments, x,y)參數(shù)x,y是slice()方法執(zhí)行時(shí)傳入的參數(shù)



(2)
slice()方法 ----- 截取數(shù)組的一部分役听,返回截取部分的新數(shù)組,不改變?cè)瓟?shù)組
slice(start, end)方法甜滨,截取數(shù)組的一部分衣摩,start是啟始位置捂敌,end是終止位置(不包含)
數(shù)組的slice()方法不加參數(shù)時(shí),等于數(shù)組的拷貝



實(shí)例:

Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b']
--- 將slice()方法中的this綁定在參數(shù)對(duì)象上栏渺,并在參數(shù)對(duì)象的作用域內(nèi)執(zhí)行slice()方法

函數(shù)實(shí)例的call方法锐涯,可以指定函數(shù)內(nèi)部this的指向(即:函數(shù)執(zhí)行時(shí)所在的作用域磕诊,--- 函數(shù)運(yùn)行時(shí)所在的對(duì)象 ),然后在所指定的作用域中纹腌,調(diào)用該函數(shù)霎终。

  • 函數(shù)實(shí)例的call方法,可以指定函數(shù)內(nèi)部this的指向升薯,指定函數(shù)運(yùn)行時(shí)所在的對(duì)象莱褒,然后在指定的作用域中,執(zhí)行該函數(shù)涎劈。
  • call方法會(huì)執(zhí)行函數(shù)广凸,無需手動(dòng)調(diào)用
  • call方法的參數(shù)是一個(gè)對(duì)象阅茶,如果參數(shù)是空,null谅海,undefined脸哀,則默認(rèn)傳入全局對(duì)象window
  • call方法可以接受多個(gè)參數(shù) :
    第一個(gè)參數(shù)是this所要指向的對(duì)象。
    后面的參數(shù)是函數(shù)調(diào)用時(shí)扭吁,所需的參數(shù)
var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true    


--- 把f函數(shù)的this綁定在obj對(duì)象上撞蜂,并在obj的作用域中,執(zhí)行f函數(shù)
var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456


--- 參數(shù)是null侥袜,空蝌诡,undefined時(shí)送漠,默認(rèn)傳入的是全局對(duì)象 window

Function.prototype.apply()

apply方法的作用與call方法類似闽寡,也是改變this指向,然后再調(diào)用該函數(shù)涎永。唯一的區(qū)別就是,它接收一個(gè)數(shù)組作為函數(shù)執(zhí)行時(shí)的參數(shù)

  • apply()方法也是改變方法中this的執(zhí)行妈倔,和call()相同
  • apply() 與 call() 方法不同的是,apply接收的參數(shù)是一個(gè)數(shù)組
  • apply()當(dāng)?shù)谝粋€(gè)參數(shù)是null捧挺,空闽烙,undefined時(shí)捕发,默認(rèn)傳入的是全局對(duì)象window
func.apply(ojb, [arg1, arg2, ...])


apply()方法:
第一個(gè)參數(shù)充石,是this所要綁定的對(duì)象拉岁,this所要指向的對(duì)象
第二個(gè)參數(shù)是一個(gè)數(shù)組喊暖,會(huì)將成員依次作為函數(shù)調(diào)用時(shí)的參數(shù)
function f(x, y){
  console.log(x + y);
}

f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2

解析:
f()函數(shù),本來是接受兩個(gè)參數(shù)巩掺,但在使用apply方法后,就可以變成独令,接受一個(gè)數(shù)組為參數(shù)

應(yīng)用:

  1. 找出數(shù)組中最大的數(shù)---(或者最小的數(shù))
Math.max(1,2,5,3) // 5
Math.min(1,2,3) // 1



const arr = [1,6,2,3,4,5];
Math.max.apply(null, arr) // 6   將max方法中的this指向頂層對(duì)象,參數(shù)是arr數(shù)組
等于:Math.max.apply(undefined, arr)
等于:Math.max([...arr])
  1. 將數(shù)組的 ( 空元素 ) 變成 ( undefined )
  • 通過apply方法遍膜,利用Array構(gòu)造函數(shù)將數(shù)組的空元素變成undefined。
  • 空元素與undefined的差別在于挽懦,數(shù)組的forEach方法會(huì)跳過空元素冀偶,但是不會(huì)跳過undefined。因此客年,遍歷內(nèi)部元素的時(shí)候量瓜,會(huì)得到不同的結(jié)果。
Array.apply(null, ['a', ,'b'])
等于: [...['a', , 'b']]


// [ 'a', undefined, 'b' ]
  1. 轉(zhuǎn)換類似數(shù)組的對(duì)象
  • 現(xiàn)在有了展開運(yùn)算符,apply方法的各種運(yùn)用都可以用展開運(yùn)算符或者其他es6語法代替

Function.prototype.bind()

bind方法用于將函數(shù)體內(nèi)的this綁定到某個(gè)對(duì)象杠纵,然后返回一個(gè)新函數(shù)。

  • bind方法不主動(dòng)執(zhí)行函數(shù)
  • call方法apply方法都在綁定函數(shù)this指向的對(duì)象后韩容,在指向?qū)ο蟮淖饔糜騼?nèi)主動(dòng)執(zhí)行該函數(shù)
  • bind方法的參數(shù),就是所要綁定的this對(duì)象
  • bind可以接收多個(gè)參數(shù)请梢,第一個(gè)參數(shù)是要綁定的this的對(duì)象,其他參數(shù)是原函數(shù)的參數(shù)
  • 如果bind方法的第一個(gè)參數(shù)是null或undefined够坐,等于將this綁定到全局對(duì)象梯影,函數(shù)運(yùn)行時(shí)this指向頂層對(duì)象(瀏覽器為window)
var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};
var func = counter.inc.bind(counter);
func();
counter.count // 1


解析:
1. 
將counter.inc方法中的this綁定在counter對(duì)象上
如果不綁定,var func = counter.inc將該方法賦值給變量后感猛,this指向了頂層對(duì)象window
var add = function (x, y) {
  return x * this.m + y * this.n;
}

var obj = {
  m: 2,
  n: 2
};

var newAdd = add.bind(obj, 5);   // add函數(shù)的第一個(gè)參數(shù)
newAdd(5) // 20                  // add函數(shù)的第二個(gè)參數(shù)

bind函數(shù)注意點(diǎn)

  • bind方法每運(yùn)行一次戳寸,就返回一個(gè)新函數(shù)疫鹊。
  • 結(jié)合回調(diào)函數(shù)使用 -------------( 重要 )

回調(diào)函數(shù)是 JavaScript 最常用的模式之一聋迎,但是一個(gè)常見的錯(cuò)誤是,將包含this的方法直接當(dāng)作回調(diào)函數(shù)牺堰。解決方法就是使用bind方法,將counter.inc綁定counter筏养。

  • 不能將含有this的方法直接當(dāng)做回調(diào)函數(shù)。而應(yīng)該用bind方法茎辐,將this綁定給原對(duì)象上
var counter = {
  count: 0,
  inc: function () {
    'use strict';
    this.count++;
  }
};

function callIt(callback) {
  callback();
}

callIt(counter.inc.bind(counter));
counter.count // 1

構(gòu)造函數(shù)的缺點(diǎn)

同一個(gè)構(gòu)造函數(shù)的多個(gè)實(shí)例之間废膘,無法共享屬性,從而造成對(duì)系統(tǒng)資源的浪費(fèi)灌闺。

  • 構(gòu)造函數(shù)內(nèi)部,通過this定義的屬性,在使用new命令生成實(shí)例對(duì)象的時(shí)候宅此,這些屬性會(huì)定義在實(shí)例對(duì)象上,即 hasOwnProperty 為 true ---------- ( 重要 )
function Cat(name, color) {
  this.name = name;
  this.color = color;
  this.meow = function () {
    console.log('喵喵');
  };
}
var cat1 = new Cat('大毛', '白色');
var cat2 = new Cat('二毛', '黑色');
cat1.meow === cat2.meow  --- 不相等,函數(shù)是引用類型的數(shù)據(jù)枝嘶,說明無法共享屬性
// false



obj.hasOwnProperty(prop) --- 表示:prop是否是obj的自身屬性,不含繼承屬性
cat1.hasOwnProperty('name'); // true



總結(jié):
1. 構(gòu)造函數(shù)內(nèi)部定義的屬性穷当,在生成實(shí)例對(duì)象的時(shí)候,會(huì)成為實(shí)例對(duì)象自身的屬性汪疮。
2. 構(gòu)造函數(shù)各個(gè)實(shí)例之間無法共享屬性卖丸,造成系統(tǒng)資源浪費(fèi)
3. 解決辦法是 原型對(duì)象

prototype原型對(duì)象

原型對(duì)象的所有屬性和方法,都能被實(shí)例對(duì)象所共享。

  • 也就是說弦撩,如果屬性和方法定義在原型對(duì)象上,那么所有實(shí)例對(duì)象就能共享這些屬性和方法
  • 構(gòu)造函數(shù)生成的實(shí)例之間無法共享構(gòu)造函數(shù)的屬性和方法偏形,因?yàn)檫@些屬性和方法是生成在實(shí)例上的
  • 對(duì)于構(gòu)造函數(shù)來說队橙,prototype屬性會(huì)在生成實(shí)例對(duì)象的時(shí)候,成為實(shí)例對(duì)象的原型對(duì)象(那么原型對(duì)象的屬性和方法就能被實(shí)例對(duì)象所共享)
  • 原型對(duì)象的屬性贮匕,不是實(shí)例對(duì)象自身的屬性。修改原型對(duì)象敦锌,變動(dòng)就立刻體現(xiàn)在所有實(shí)例對(duì)象上
  • 當(dāng)實(shí)例對(duì)象本身沒有某個(gè)屬性和方法時(shí),會(huì)在原型對(duì)象上尋找該屬性和方法腥刹,沒找到,在去原型的原型上找录别。直到Object.prototype上都沒找到朽色,就返回undefined

總結(jié):
原型對(duì)象的作用就是定義: 所有實(shí)例對(duì)象所共享的屬性和方法

function Animal(name) {
  this.name = name;
}
Animal.prototype.color = 'white';  
// 構(gòu)造函數(shù)的prototype屬性在生成實(shí)例對(duì)象時(shí),會(huì)成為實(shí)例的原型對(duì)象
// prototype對(duì)象上的color屬性组题,會(huì)被實(shí)例共享
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');

cat1.color // 'white'
cat2.color // 'white'

原型鏈

所有對(duì)象都有自己原型對(duì)象

  • 所有對(duì)象都繼承了Object.prototype對(duì)象的屬性和方法葫男,這就是所有對(duì)象都具有valueOf方法 和toString方法的原因,都繼承自O(shè)bject.prototype對(duì)象
  • Object.prototype 的原型是 null崔列, null沒有任何屬性和方法,也沒有自己的原型边翼,原型鏈到此終結(jié)江滨,原型鏈的盡頭是null镊屎。
  • Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型對(duì)象 --------( 重要 )
  • 如果自身和原型上都定義了同名的屬性,則優(yōu)先讀取自身屬性。'overriding'
Object.getPrototypeOf(Object.prototype)

Object.getPrototypeOf() --- 返回參數(shù)對(duì)象的原型對(duì)象

// null
// 表示Object.prototype對(duì)象的原型對(duì)象是null
var MyArray = function () {};

MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;

var mine = new MyArray();    
mine.push(1, 2, 3);
mine.length // 3
mine instanceof Array // true



解析:
1. mine 是構(gòu)造函數(shù)MyArray 生成實(shí)例對(duì)象
2. 構(gòu)造函數(shù)的 MyArray.prototype對(duì)象成為實(shí)例對(duì)象的原型對(duì)象
3. MyArray.prototype指向了數(shù)組實(shí)例,那么MyArray的實(shí)例就具有 數(shù)組的屬性和方法
4. 所有mine具有數(shù)組的屬性和方法
5. instanceof運(yùn)算符    左邊是實(shí)例   右邊是構(gòu)造函數(shù)    返回布爾值

constructor屬性

prototype對(duì)象有一個(gè)constructor屬性桶蛔,默認(rèn)指向 prototype對(duì)象所在的構(gòu)造函數(shù)斩郎。---------------------------------------------------- ( 重要 )

  • constructor屬性定義在prototype對(duì)象上姻蚓,就意味著可以被所有實(shí)例所繼承(prototype對(duì)象是實(shí)例對(duì)象的原型對(duì)象, 實(shí)例對(duì)象繼承原型對(duì)象的屬性和方法)
  • constructor屬性的作用,用來確定實(shí)例對(duì)象由哪個(gè)構(gòu)造函數(shù)生成
  • 利用constructor屬性可以從一個(gè)實(shí)例對(duì)象新建另一個(gè)實(shí)例對(duì)象
  • constructor屬性表示原型對(duì)象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系扑浸,如果修改了原型對(duì)象,一般會(huì)同時(shí)修改constructor屬性桥言,防止引用的時(shí)候出錯(cuò)枯夜。
( 重要 )


function P() {}
P.prototype.constructor === P // true


解析:
1. P構(gòu)造函數(shù)(首字母大寫)的prototype屬性是一個(gè)對(duì)象
2. prototype對(duì)象的constructor屬性指向prototype對(duì)象所在的構(gòu)造函數(shù)
3. P.prototype.constructor === P 布爾值就是true
( 重要 )


function P() {}
var p = new P();
p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false  是繼承的,不是自身的屬性


解析:
1. prototype對(duì)象的constructor屬性,指向prototype對(duì)象所在構(gòu)造函數(shù)
2. constructor是實(shí)例對(duì)象的原型對(duì)象的屬性楞遏,會(huì)被實(shí)例所繼承
   所以 
   實(shí)例p繼承了constructor屬性沧奴,p.constructor = P = P.prototype.constructor

利用constructor屬性灶芝,可以從一個(gè)實(shí)例生成另一個(gè)實(shí)例
因?yàn)? constructor屬性指向的就是構(gòu)造函數(shù)




function Constr() {}
var x = new Constr();
var y = new x.constructor();   //注意x.constructor === Constr,這里要執(zhí)行
// x.constructor間接調(diào)用構(gòu)造函數(shù)
y instanceof Constr // true
  • constructor屬性表示原型對(duì)象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系蜘腌,如果修改了原型對(duì)象养泡,一般會(huì)同時(shí)修改constructor屬性惩妇,防止引用的時(shí)候出錯(cuò)路召。
( 重要 )


function Person(name) {
  this.name = name;
}
Person.prototype.constructor === Person // true
Person.prototype = {
  method: function () {}
};
Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true


解析:
1. Person.prototype 修改成了對(duì)象
2. 構(gòu)造函數(shù)Person的原型對(duì)象改了,但沒改constructor屬性馍乙,導(dǎo)致這個(gè)屬性不再指向Person
3. 對(duì)象的構(gòu)造函數(shù)是Object構(gòu)造函數(shù)
4. 所以修改原型對(duì)象時(shí)丝格,一般要同時(shí)修改constructor屬性的指向

instanceof運(yùn)算符

instanceof運(yùn)算符返回一個(gè)布爾值撑瞧,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例。

  • instanceof運(yùn)算符返回的是boolean值
  • 表示 ( 對(duì)象 ) 是否是 ( 構(gòu)造函數(shù) ) 的 ( 實(shí)例 )
  • instance:是實(shí)例的意思
  • ( instanceof ) 運(yùn)算符 ( 左邊是實(shí)例對(duì)象 )显蝌,( 右邊是構(gòu)造函數(shù) )季蚂。
  • 它會(huì)檢查右邊構(gòu)造函數(shù)的原型對(duì)象prototype, 是否在左邊對(duì)象的原型鏈上。
  • 由于instanceof檢查整個(gè)原型鏈琅束,因此同一個(gè)實(shí)例對(duì)象扭屁,可能會(huì)對(duì)多個(gè)構(gòu)造函數(shù)都返回true。
  • instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype屬性涩禀,是否在左邊對(duì)象的原型鏈上料滥。
  • 有一種特殊情況,就是左邊對(duì)象的原型鏈上艾船,只有null對(duì)象葵腹。這時(shí),instanceof判斷會(huì)失真屿岂。
  • instanceof運(yùn)算符的一個(gè)用處践宴,是判斷值的類型。
( 重要 )


v instanceof Vehicle       --------------  v是否是Vehicle的實(shí)例
// 等同于
Vehicle.prototype.isPrototypeOf(v)  -----  Vehicle.prototype是否是v的原型


解析:
1. isPrototypeOf() 方法允許你檢查一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上
2. isPrototypeOf()返回的是布爾值
  • instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype屬性爷怀,是否在左邊對(duì)象的原型鏈上阻肩。有一種特殊情況,就是左邊對(duì)象的原型鏈上运授,只有null對(duì)象烤惊。這時(shí),instanceof判斷會(huì)失真吁朦。
( 重要 )


var obj = Object.create(null);
typeof obj // "object"
Object.create(null) instanceof Object // false


解析:
1. Object.create()
   該方法接受一個(gè)對(duì)象作為參數(shù)柒室,然后以它為原型,返回一個(gè)實(shí)例對(duì)象逗宜。
   該實(shí)例完全繼承原型對(duì)象的屬性雄右。
   即:object.create()方法  以參數(shù)對(duì)象為原型,生成實(shí)例對(duì)象
2. instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype對(duì)象是否在左邊對(duì)象的原型鏈上
3. Object.create(null) instanceof Object
    因?yàn)橛疫?Object.prototype === null纺讲,不在左邊對(duì)象的原型鏈上
    左邊對(duì)象的原型鏈在Object.prototype對(duì)象上終止

instanceof 用來判斷值得類型

但是注意:instanceof 運(yùn)算符只能用于對(duì)象擂仍,不適用原始類型的值。

此外刻诊,對(duì)于 undefined 和 null 防楷,instanceOf 運(yùn)算符總是返回 false。



var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true
undefined instanceof Object // false
null instanceof Object // false

Object.getPrototypeOf()

Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型则涯,是獲取原型對(duì)象的標(biāo)準(zhǔn)方法

( 重要 )


var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true


解析:
1. Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型
2. f 的原型是 構(gòu)造函數(shù)F的 prototype屬性

幾種特殊對(duì)象的原型


1. 空對(duì)象的原型是 Object.prototype

2. Object.prototype 的原型是 null

3. 函數(shù)的原型是 Function.prototype

Object.setPrototypeOf() --- 注意 返回的是參數(shù)對(duì)象

Object.setPrototypeOf方法為參數(shù)對(duì)象設(shè)置原型复局,返回該參數(shù)對(duì)象。它接受兩個(gè)參數(shù)粟判,第一個(gè)是現(xiàn)有對(duì)象亿昏,第二個(gè)是原型對(duì)象。

  • Object.setPrototypeOf() 返回該參數(shù)對(duì)象档礁。
  • Object.setPrototypeOf() 接受兩個(gè)參數(shù)角钩,第一個(gè)是現(xiàn)有對(duì)象(參數(shù)對(duì)象),第二個(gè)是原型對(duì)象
  • Object.setPrototypeOf() 為參數(shù)對(duì)象設(shè)置原型
( 重要 )


var a = {};
var b = {x: 1};
Object.setPrototypeOf(a, b);    // {}
Object.getPrototypeOf(a) === b // true
a.x // 1


解析:
1. Object.setPrototypeOf(參數(shù)對(duì)象,原型對(duì)象)  ---  返回的是參數(shù)對(duì)象
2. Object.setPrototypeOf()方法的作用是: 把第二個(gè)參數(shù)設(shè)置成第一個(gè)參數(shù)的原型
  • new命令可以使用Object.setPrototypeOf方法模擬递礼。
( 重要 )  --- new命令的原理



var F = function () {
  this.foo = 'bar';
};
var f = new F();
// 等同于
var f = Object.setPrototypeOf({}, F.prototype);  --- 將空對(duì)象的原型設(shè)置成 F的prototype屬性
F.call(f);   --------------------------------------- 將F中的this指向 空對(duì)象惨险,并執(zhí)行構(gòu)造函數(shù)

Object.create() --- 返回參數(shù)對(duì)象的實(shí)例對(duì)象

Object.create()接受一個(gè)對(duì)象作為參數(shù),然后以它為原型脊髓,返回一個(gè)實(shí)例對(duì)象辫愉。該實(shí)例完全繼承原型對(duì)象的屬性。

  • Object.create() 以參數(shù)對(duì)象為原型将硝,返回實(shí)例對(duì)象恭朗。
// 原型對(duì)象
var A = {
  print: function () {
    console.log('hello');
  }
};

// 實(shí)例對(duì)象
var B = Object.create(A);

Object.getPrototypeOf(B) === A // true
B.print() // hello
B.print === A.print // true
  • 下面三種方式生成的新對(duì)象是等價(jià)的。
var obj1 = Object.create({});
var obj2 = Object.create(Object.prototype);
var obj3 = new Object();
  • 如果想要生成一個(gè)不繼承任何屬性(比如沒有toString和valueOf方法)的對(duì)象依疼,可以將Object.create的參數(shù)設(shè)為null痰腮。
var obj = Object.create(null);

obj.valueOf()
// TypeError: Object [object Object] has no method 'valueOf
  • 使用Object.create方法的時(shí)候,必須提供對(duì)象原型律罢,如果參數(shù)為空膀值,或者不是對(duì)象,都會(huì)報(bào)錯(cuò)弟翘。
Object.create()
// TypeError: Object prototype may only be an Object or null
Object.create(123)
// TypeError: Object prototype may only be an Object or null
  • Object.create方法生成的新對(duì)象虫腋,動(dòng)態(tài)繼承了原型。在原型上添加或修改任何方法稀余,會(huì)立刻反映在新對(duì)象之上悦冀。
var obj1 = { p: 1 };
var obj2 = Object.create(obj1);

obj1.p = 2;
obj2.p // 2
  • Object.create方法生成的對(duì)象,繼承了它的原型對(duì)象的構(gòu)造函數(shù)睛琳。
( 重要 )


function A() {}
var a = new A();
var b = Object.create(a);
b.constructor === A // true
b instanceof A // true


解析:
1. Object.create()方法生成的對(duì)象盒蟆,繼承了它的原型對(duì)象的構(gòu)造函數(shù)
2. var b = Object.create(a); ---- b的原型是a,  b繼承了a的構(gòu)造函數(shù)
   所以 b.constructor === A // true
   所以 b instanceof A // true

Object.prototype.isPrototypeOf() - 返回布爾值

isPrototypeOf方法被實(shí)例對(duì)象所繼承

實(shí)例對(duì)象的 isPrototypeOf() 方法,用來判斷該對(duì)象是否是參數(shù)對(duì)象的原型

  • 只要實(shí)例對(duì)象處在參數(shù)對(duì)象的原型鏈上师骗, isPrototypeOf 方法就返回true

Object.prototype.__proto__

  • 實(shí)例對(duì)象的__proto__返回該實(shí)例對(duì)象的原型
  • __proto__該屬性可讀寫
  • 只需要瀏覽器才需要部署該屬性历等,是一個(gè)內(nèi)部屬性
  • 盡量少用__proto__屬性,而是使用
    Object.getPrototypeOf()讀參數(shù)對(duì)象的原型
    Object.setPrototypeOf()寫第一個(gè)參數(shù)對(duì)象的原型為第二個(gè)參數(shù)對(duì)象
componentDidMount() {
   const obj1 = {};
   const obj2 = {'name': 'wang'};
   obj1.__proto__ = obj2;
   console.log(obj2.isPrototypeOf(obj1), '實(shí)例對(duì)象的isPrototypeOf()放回一個(gè)布爾值辟癌,表示實(shí)例對(duì)象是否是參數(shù)對(duì)象的原型');
   console.log(Object.getPrototypeOf(obj1), 'getPrototypeOf()方法寒屯,返回參數(shù)對(duì)象的原型對(duì)象');
}

獲取原型對(duì)象的方法比較

獲取實(shí)例對(duì)象的原型有三種方法: Object.getPrototypeOf()勝出

  1. obj.__proto__實(shí)例對(duì)象繼承的 __proto__屬性
  2. obj.constructor.prototype
    ----- 實(shí)例的constructor是繼承自實(shí)例構(gòu)造函數(shù)的 prototype上的constructor
  3. Object.getPrototypeOf()
(重要)  -- 比較三種獲取原型的方法



1. __proto__ 只在瀏覽器上有     ---- 不靠譜
2. obj.constructor.prototype在手動(dòng)修改原型時(shí),還要修改構(gòu)造函數(shù)黍少,否則可能會(huì)失效



結(jié)論:使用Object.getPrototypeOf() 最好

Object.prototype.hasOwnProperty

判斷某個(gè)屬性寡夹,是在對(duì)象自身屬性還是繼承屬性

  • 實(shí)例對(duì)象的 hasOwnProperty 屬性返回一個(gè)布爾值,用于判斷某個(gè)屬性定義在對(duì)象自身厂置,還是定義在原型鏈上
  • hasOwnProperty是js中唯一一個(gè)處理對(duì)象屬性時(shí)菩掏,不會(huì)遍歷原型鏈的方法

in運(yùn)算符

in運(yùn)算符返回一個(gè)布爾值,表示一個(gè)對(duì)象是否具有某個(gè)屬性

  • 注意: ( in ) 運(yùn)算符 ( 不區(qū)分 ) 是 ( 自身屬性 ) 還是 ( 繼承屬性 )

for ...in 循環(huán)

自身屬性和繼承屬性都會(huì)被for...in循環(huán)遍歷

  • 為了只遍歷自身屬性昵济,可以在for...in循環(huán)內(nèi)部智绸,用hasOwnProperty來過濾只有是自身屬性時(shí)野揪,才遍歷
 const obj1 = {'name': 'wang'};
 const obj2 = {'age': 20};
 Object.setPrototypeOf(obj1, obj2);

 for(let x in obj1) {
     console.log(x, 'x') 
  }
 // name x
 // age x
 
 for(let y in obj1) {
    if( obj1.hasOwnProperty(y) ) {   ---- 參數(shù)屬性是否是實(shí)例對(duì)象的自身屬性
       console.log(y, 'y')
     }
 }
 // name y

對(duì)象的拷貝

如何要拷貝對(duì)象,需要有兩點(diǎn)相同

  1. 拷貝后的對(duì)象瞧栗,要與原對(duì)象具有相同的 原型對(duì)象
  2. 考背后的對(duì)象斯稳,要與元對(duì)象具有相同的 實(shí)例屬性



















2018-7-1

語句

js程序的執(zhí)行單位是 (行),一般情況下沼溜,每一行就是一個(gè)語句平挑。

  • 語句是為了完成某種任務(wù)而進(jìn)行的操作
  • 語句以分號(hào)結(jié)尾,一個(gè)分號(hào)就表示一個(gè)語句的結(jié)束
  • 多個(gè)語句可以寫在一行內(nèi)
  • 分號(hào)前面可以沒有任何內(nèi)容系草,js將其視為空語句
var a = 1 + 3 ; var b = 'abc';


解析:
1. 語句:語句以分號(hào)結(jié)尾;多個(gè)語句可以寫在一行內(nèi)唆涝。
2. 表達(dá)式:為了得到返回值的計(jì)算式
3. 凡是預(yù)期為值的地方找都,都可以使用表達(dá)式
4. 賦值語句,等號(hào)右邊預(yù)期為值廊酣,所以可以使用各種表達(dá)式

表達(dá)式

表達(dá)式: 是一個(gè)為了得到返回值的計(jì)算式

語句和表達(dá)式的區(qū)別

  • 語句是為了完成某種任務(wù)而進(jìn)行的操作能耻,一般不需要返回值

  • 表達(dá)式是為了得到返回值,一定會(huì)返回一個(gè)值

  • js中亡驰,凡是預(yù)期為值的地方晓猛,都可以使用表達(dá)式(重要

變量

變量是對(duì)值的具名引用

  • 變量是對(duì)值的 具名引用
  • 變量就是為值取名 ,引用這個(gè)名字凡辱,就是引用這個(gè)值 ----------------------------- ( 重要 )
  • 變量的名字戒职,就是變量名
  • 變量名區(qū)分大小寫
  • 如果只是聲明變量裸燎,而未賦值揍堕,則改變量的值是 undefined
  • 可以在同一條var命令中聲明多個(gè)變量
  • JavaScript 是一種動(dòng)態(tài)類型語言涛癌,也就是說弛秋,變量的類型沒有限制古毛,變量可以隨時(shí)更改類型

函數(shù)

js把函數(shù)看成一種值牺六,凡是能使用值的地方丝蹭,就能使用函數(shù)

  • 當(dāng)有return語句時(shí)秤掌,返回return后面緊跟的表達(dá)式
  • 沒有return語句時(shí)汉操,返回undefined
  • 函數(shù)只是一個(gè)可執(zhí)行的值
  • (表達(dá)式是為了得到返回值的計(jì)算式再来,目的是為了得到返回值,預(yù)期為值的地方磷瘤,都可以使用表達(dá)式)
  • 函數(shù)與其他數(shù)據(jù)類型地位相等芒篷,叫做第一等公民

函數(shù)名的提升

js將函數(shù)名,視同變量名膀斋。

  • 在用function命令聲明函數(shù)時(shí)梭伐,function后面的變量名存在變量提升
  • 注意:采用變量賦值時(shí),如果先調(diào)用就會(huì)報(bào)錯(cuò)
  • 因此仰担,如果同時(shí)采用function命令和賦值語句聲明同一個(gè)函數(shù)糊识,最后總是采用賦值語句的定義绩社。
  • 不能在條件語句中聲明函數(shù) ( if ) 和 ( try )
( 重要 )



總結(jié): 
用變量賦值的方法聲明函數(shù),和function聲明都存在變量提升
但是:變量賦值先調(diào)用會(huì)報(bào)錯(cuò)赂苗,而function聲明不會(huì)報(bào)錯(cuò)
( 先調(diào)用函數(shù)愉耙,function聲明不報(bào)錯(cuò),變量賦值聲明報(bào)錯(cuò) )




1. function命令聲明時(shí)的 ( 函數(shù)名提升 )
f();
function f() {}
不會(huì)報(bào)錯(cuò)




2. 變量賦值聲明函數(shù)
f();
var f = function (){};
報(bào)錯(cuò)TypeError: undefined is not a function拌滋,----------------  實(shí)際上相當(dāng)于下面的代碼:
var f;
f();
f = function () {};

函數(shù)的name屬性

返回函數(shù)的名字

  • function聲明的函數(shù)朴沿,返回function后面的函數(shù)名
  • 變量賦值,匿名函數(shù)败砂,返回變量名
  • 變量賦值赌渣,具名函數(shù),返回function后面的函數(shù)名
  • name屬性的用處昌犹,就是獲得參數(shù)函數(shù)的名字
var myFunc = function () {};
function test(f) {
  console.log(f.name);
}
test(myFunc)    ----------------------- 返回 myFunc


上面代碼中坚芜,函數(shù)test內(nèi)部通過name屬性,就可以知道傳入的參數(shù)是什么函數(shù)斜姥。

length屬性

函數(shù)的length返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)

  • 返回 ( 定義時(shí) ) 的 ( 參數(shù)個(gè)數(shù) )
  • length方法提供了一種機(jī)制鸿竖,判斷定義時(shí)和調(diào)用時(shí)參數(shù)的差異,以便實(shí)現(xiàn)面向?qū)ο缶幊痰?br> ( 方法重載 ) overload
const a = function(a,b,c) {
  return `${a},$铸敏,${c}`
};
console.log( a.length ); -------------------------  length返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù): 3
console.log( a(1,2) );    // 1,2,undefined

函數(shù)的toString方法

  • toString方法返回一個(gè)字符串缚忧,內(nèi)容時(shí)函數(shù)的源碼 ( 包括函數(shù)內(nèi)部的注釋代碼 )
    總結(jié): name屬性,length屬性,toString()方法
const a = function(a,b,c) {
    return `${a},$杈笔,${c}`
};
console.log( a.toString(), 'toString方法闪水,返回函數(shù)的源碼字符串' )
console.log( a.length, 'length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)' );
console.log( a.name, 'name屬性返回函數(shù)的名字桩撮,function命令聲明敦第,時(shí)后面的函數(shù)名,變量賦值店量,匿名時(shí)變量名芜果,具名時(shí)function后的函數(shù)名')
console.log( a(1,2) );




結(jié)果:
function a(_a, b, c) {
                return _a + ',' + b + ',' + c;
            } toString方法,返回函數(shù)的源碼字符串
3 "length屬性融师,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)"
a name屬性返回函數(shù)的名字右钾,function命令聲明,時(shí)后面的函數(shù)名旱爆,變量賦值舀射,匿名時(shí)變量名,具名時(shí)function后的函數(shù)名
1,2,undefined

函數(shù)的作用域

( 作用域 ) scope指的是 ( 變量存在的范圍 )
es5有兩種作用域:( 全局作用域 ) 和 ( 函數(shù)作用域 )
es6新增一個(gè)作用域:( 塊級(jí)作用域 )

  • 全局作用域:在整個(gè)程序中存在怀伦,任何地方都可以讀取
  • 函數(shù)作用域:只能在函數(shù)內(nèi)部讀取脆烟,函數(shù)外部無法讀取。( 用回調(diào)函數(shù)解決 )
  • 塊級(jí)作用域: 只在代碼塊內(nèi)有效
  • 函數(shù)外部聲明的變量房待,是全局變量邢羔,可以在函數(shù)內(nèi)部讀取 (global variable全局變量)
  • 函數(shù)內(nèi)部定義的變量驼抹,函數(shù)外部無法讀取,稱為局部變量 (local variable局部便變量)
  • 函數(shù)內(nèi)部定義的變量拜鹤,會(huì)在該作用域內(nèi)框冀,覆蓋同名全局變量
  • 注意: 對(duì)于var命令,局部變量只能在函數(shù)內(nèi)部聲明敏簿,在其他區(qū)塊聲明明也,一律都是全局變量

var a = 1;
var c = 3;

function x() {
    console.log(a, '函數(shù)內(nèi)部,可以讀取函數(shù)外部的全局變量');
    var b = 2;
    var c = 4;
    console.log(c, '函數(shù)內(nèi)部定義的變量惯裕,會(huì)在該作用域內(nèi)覆蓋同名全局變量')
}
x();

if(true) {
    var y = 100;
}
console.log(y, '對(duì)于var命令來說温数,局部變量只能在函數(shù)中聲明,在其他區(qū)塊中聲明的變量都是全局變量')
console.log(b, '函數(shù)外部無法讀取函數(shù)內(nèi)部的變量')

函數(shù)內(nèi)部的變量提升

  • 和全局作用域一樣轻猖,函數(shù)作用域也會(huì)產(chǎn)生變量提升現(xiàn)象
  • var聲明的變量帆吻,不管在什么位置,變量聲明都會(huì)被提到函數(shù)頭部
function foo(x) {
  if (x > 100) {
    var tmp = x - 100;
  }
}
 -- 等同于
function foo(x) {
  var tmp;
  if (x > 100) {
    tmp = x - 100;
  };
}

函數(shù)本身的作用域

函數(shù)本身也是一個(gè)值咙边,也有自己的作用域

  • 函數(shù)就是一個(gè)計(jì)算的值,凡是使用值的地方都可以使用函數(shù)
  • 表達(dá)式就是為了得到返回值的計(jì)算式次员,目的是為了得到返回值败许,凡是預(yù)期為值的地方,都可以使用表達(dá)式
  • 函數(shù)的作用域淑蔚,是其聲明時(shí)所在的作用域市殷,與其運(yùn)行時(shí)的作用域無關(guān)
  • 函數(shù)的作用域,是函數(shù)聲明時(shí)的作用域刹衫,與函數(shù)運(yùn)行時(shí)的作用域無關(guān)
  • 函數(shù)運(yùn)行時(shí)的作用域醋寝,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān)
  • 容易犯錯(cuò)的點(diǎn): 如果a函數(shù)調(diào)用b函數(shù)带迟,卻沒有考慮到b函數(shù)不會(huì)引用a函數(shù)內(nèi)部的變量 --------- ( 重要 )
var a = 1;
function x() {
    console.log(a, '函數(shù)的作用域音羞,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān)');
    console.log('容易犯錯(cuò)的點(diǎn): 如果a函數(shù)調(diào)用b函數(shù)仓犬,卻沒有考慮到b函數(shù)不會(huì)引用a函數(shù)的變量');
}
function y() {
    var a = 100;
    x();
}
y();  ---------------- 結(jié)果是1

總結(jié):

  1. 函數(shù)外部聲明的函數(shù)嗅绰,作用域綁定在函數(shù)外部
  2. 函數(shù)內(nèi)部聲明的函數(shù),作用域綁定在函數(shù)內(nèi)部
( 重要 )



總結(jié):
1. 函數(shù)外部聲明的函數(shù)搀继,作用域綁定在函數(shù)外部
2. 函數(shù)內(nèi)部聲明的函數(shù)窘面,作用域綁定在函數(shù)內(nèi)部
       第一個(gè)和第二點(diǎn)都滿足第三點(diǎn)
3. 函數(shù)的作用域,是函數(shù)聲明時(shí)的作用域叽躯,與函數(shù)調(diào)用時(shí)的作用域無關(guān) !!!!!!!!


(1)
var a = 1;
var x = function () {
  console.log(a);
};
function y(f) {
  var a = 2;
  f();
}
y(x)   -------- 結(jié)果是1   ( 函數(shù)的作用域财边,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān) )



(2)
function foo() {
  var x = 1;
  function bar() {
    console.log(x);
  }
  return bar;
}
var x = 2;
var f = foo();
f()   -------- 結(jié)果是1   ( 函數(shù)的作用域点骑,是函數(shù)聲明時(shí)的作用域酣难,與函數(shù)調(diào)用時(shí)的作用域無關(guān) )

參數(shù)

  • 函數(shù)沒辦法省略靠前的參數(shù)谍夭,而保留靠后的參數(shù)
  • 如果一點(diǎn)要省略靠前的參數(shù),只有顯示的傳入 undefined
function f(a, b) {
  return a;
}

f( , 1) // SyntaxError: Unexpected token ,(…)   省略前面報(bào)錯(cuò)
f(undefined, 1) // undefined   一定要省略前面鲸鹦,則只要傳入undefined

參數(shù)的傳遞方式

    1. 函數(shù)的參數(shù)如果是原始類型的值(數(shù)值慧库,字符串,布爾值)馋嗜,傳遞方法是( 傳值傳遞 )齐板,
      傳遞的是原始值的拷貝,在函數(shù)體內(nèi)修改參數(shù)葛菇,不會(huì)影響到函數(shù)外部
    1. 函數(shù)的參數(shù)是復(fù)合類型的值(數(shù)組甘磨,對(duì)象,其他函數(shù))眯停,傳遞方式是( 傳址傳遞 )济舆,
      傳遞的是原始值的地址指針,在函數(shù)內(nèi)部修改參數(shù)莺债,會(huì)影響到原始值
    1. 注意:如果函數(shù)內(nèi)部修改的不是參數(shù)對(duì)象的某個(gè)屬性滋觉,而是替換掉整個(gè)參數(shù),這時(shí)不會(huì)影響到原始值
  • reference是引用的意思
  • ( 變量 ) 分為 ( 基本類型 ) 和 ( 引用類型 )
let str = 'abcdef';
let num = 12345;
let boo = true;  ------------------------------------ 原始類型的值

let arr = [1,2,3,4,5];
let obj = {'name': 'wang'}; ------------------------- 復(fù)合類型的值

let replaceArr = [1,2];
let replaceObj = {'name': 'zhang'} ------------------ 復(fù)合類型的值


function pass(num,str,boo, arr,obj,fun, replaceArr,replaceObj) {
    num = 100;
    str = 'oneHundred';
    boo =  false;     ---------- 參數(shù)是原始類型的值齐邦,傳值傳遞椎侠,修改參數(shù),不影響原始值

    arr[0] = 100;
    obj.name = 'li';   --------- 參數(shù)是復(fù)合類型的值措拇,傳址傳遞我纪,修改參數(shù),影響原始值

    replaceArr = [1,1,1];
    replaceObj = {'age': 30} --- 替換掉整個(gè)復(fù)合類型的參數(shù)丐吓,不會(huì)影響到原始值
}

pass(str, num, boo, arr, obj, replaceArr, replaceObj);
console.log(str, num, boo);
console.log(arr, obj);
console.log(replaceArr, replaceObj);

 結(jié)果:
 abcdef 12345 true
 [100, 2, 3, 4, 5] {name: "li"}
 [1, 2] {name: "zhang"}

同名參數(shù)

如果有同名參數(shù)浅悉,則取最后出現(xiàn)的那個(gè)值

function f(a, a) {
  console.log(a);
}
f(1, 2) // 2

-------------------------------------

function f(a, a) {
  console.log(a);
}
f(1) // undefined

arguments對(duì)象

arguments對(duì)象包含了函數(shù) ( 運(yùn)行時(shí)的所有參數(shù) )

  • arguments[0] 是第一個(gè)參數(shù),arguments[1] 是第二個(gè)參數(shù)券犁,以此類推...
  • arguments對(duì)象只能在函數(shù)內(nèi)部使用
  • 正常模式下术健,arguments對(duì)象可以在運(yùn)行時(shí)修改
  • 嚴(yán)格模式下,arguments對(duì)象是一個(gè)只讀對(duì)象族操,修改無效苛坚,當(dāng)不會(huì)報(bào)錯(cuò)
  • arguments對(duì)象有一個(gè)callees屬性,返回它對(duì)應(yīng)的原函數(shù)
function a(b,c,d,e) {
    console.log(arguments.length, 'arguments.length返回調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)色难,是調(diào)用時(shí)的參數(shù)個(gè)數(shù)');
    arguments[0] = 100;
    console.log(arguments[0], 'arguments對(duì)象泼舱,可以在運(yùn)行時(shí)修改');
    console.log('在嚴(yán)格模式下,arguments對(duì)象是只讀枷莉,修改無效娇昙,當(dāng)不會(huì)報(bào)錯(cuò)');
}
a(1,2,3);
console.log(a.length, '函數(shù)的length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)');
console.log( arguments[1] ,'arguments對(duì)象只能在函數(shù)內(nèi)部使用')
console.log(arguments.callee, 'arguments對(duì)象的callee屬性笤妙,返回它對(duì)應(yīng)的原函數(shù)');



結(jié)果:
3 "arguments.length返回調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)冒掌,是調(diào)用時(shí)的參數(shù)個(gè)數(shù)"
100 "arguments對(duì)象噪裕,可以在運(yùn)行時(shí)修改"
在嚴(yán)格模式下,arguments對(duì)象是只讀股毫,修改無效膳音,當(dāng)不會(huì)報(bào)錯(cuò)
4 "函數(shù)的length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)"
undefined "arguments對(duì)象只能在函數(shù)內(nèi)部使用"
報(bào)錯(cuò): callee不能用于嚴(yán)格模式铃诬,react的類默認(rèn)就是嚴(yán)格模式



注意:
1. 函數(shù)的length屬性祭陷,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)
2. arguments.length屬性,返回函數(shù)調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)
3. arguments對(duì)象只能在函數(shù)內(nèi)部使用

閉包

閉包是定義在函數(shù)內(nèi)部的函數(shù)

  • 函數(shù)的作用域是函數(shù)定義時(shí)的作用域趣席,與調(diào)用時(shí)的作用域無關(guān)
  • 閉包的用處:
    1. 讀取函數(shù)內(nèi)部的變量
    1. 將這些變量保存在內(nèi)存中兵志,即閉包可以記住它的誕生環(huán)境一直存在
    1. 封裝對(duì)象的私有屬性和私有方法
( 重要 )


function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}
var n = 111;
var result = f1();
result(); // 999



解析:
1. 函數(shù)的作用域,是函數(shù)定義時(shí)的作用域宣肚,與函數(shù)調(diào)用時(shí)的作用域無關(guān)
2. f2聲明在f1的內(nèi)部想罕,f2調(diào)用時(shí),f2的作用域是定義時(shí)候的作用域霉涨,即在f1的內(nèi)部按价,所以是999,不是111
3. 閉包就是定義在一個(gè)函數(shù)內(nèi)部的函數(shù)笙瑟,注意: 一定是要在函數(shù)內(nèi)部定義 7恪!逮走!
( 閉包 )



function createIncrementor(start) {
  return function () {
    return start++;
  };
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7



解析:
1. 閉包inc使得函數(shù)createIncrementor的內(nèi)部環(huán)境,一直存在今阳。
2. inc始終在內(nèi)存中师溅,而inc的存在依賴于createIncrementor,因此也始終在內(nèi)存中
   不會(huì)在調(diào)用結(jié)束后盾舌,被垃圾回收機(jī)制回收墓臭。
  • 閉包用于封裝對(duì)象的私有屬性和私有方法
閉包:用與封裝對(duì)象的私有屬性和私有方法


function Person(name) {
  var _age;
  function setAge(n) {
    _age = n;
  }
  function getAge() {
    return _age;
  }

  return {
    name: name,
    getAge: getAge,
    setAge: setAge
  };
}

var p1 = Person('張三');外層函數(shù)每次運(yùn)行,都會(huì)生成一個(gè)新的閉包妖谴,閉包保存外層函數(shù)的內(nèi)部變量窿锉,內(nèi)存消耗大
p1.setAge(25);
p1.getAge() // 25

注意:
1. 外層函數(shù)每次運(yùn)行,都會(huì)生成一個(gè)新的閉包膝舅,而這個(gè)閉包又會(huì)保留外層函數(shù)的內(nèi)部變量嗡载,所以內(nèi)存消耗很大。
2. 因此不能濫用閉包仍稀,否則會(huì)造成網(wǎng)頁的性能問題洼滚。

立即調(diào)用函數(shù)表達(dá)式

有時(shí)候,我們需要在定義函數(shù)之后技潘,立即調(diào)用該函數(shù)遥巴。這時(shí)千康,你不能在函數(shù)的定義之后加上圓括號(hào),這會(huì)產(chǎn)生語法錯(cuò)誤铲掐。

  • 產(chǎn)生錯(cuò)誤的原因是function關(guān)鍵字拾弃,可以作為語句,也可以作為表達(dá)式
  • 語句:用分號(hào)結(jié)尾摆霉,多個(gè)語句可以在一行豪椿。
  • 表達(dá)式:為了得到返回值的計(jì)算式,凡是預(yù)期為值的地方都可以使用表達(dá)式斯入;
  • js規(guī)定砂碉,function關(guān)鍵字在行首,一律解釋成語句刻两。因此增蹭,JavaScript引擎看到行首是function關(guān)鍵字之后,認(rèn)為這一段都是函數(shù)的定義磅摹,不應(yīng)該以圓括號(hào)結(jié)尾滋迈,所以就報(bào)錯(cuò)了。
  • 解決方法就是不要讓function出現(xiàn)在行首户誓,讓引擎將其理解成一個(gè)表達(dá)式饼灿。最簡(jiǎn)單的處理,就是將其放在一個(gè)圓括號(hào)里面帝美。
  • 總結(jié):
    1. function出現(xiàn)在行首碍彭,是語句。語句不能以括號(hào)()結(jié)尾悼潭,必須以分號(hào);結(jié)尾
    1. 用變量賦值方法聲明的函數(shù)庇忌,function...是一個(gè)表達(dá)式,直接加()就能立即執(zhí)行調(diào)用
    1. 如果function在行首舰褪,又要立即調(diào)用皆疹,包一層括號(hào)即可
( 重要 )


語句
function f() {}            -------   函數(shù)的聲明語句


表達(dá)式
var f = function f() {}    --------  等號(hào)右邊預(yù)期是值,function是表達(dá)式占拍,函數(shù)就是一個(gè)可執(zhí)行的值
(function(){ ... }());         ------------- 語句不能以括號(hào)結(jié)尾略就,而是以分號(hào)結(jié)尾
// 或者
(function(){ ... })();

注意,上面兩種寫法最后的分號(hào)都是必須的晃酒。
如果省略分號(hào)表牢,遇到連著兩個(gè) IIFE,可能就會(huì)報(bào)錯(cuò)掖疮。




--------------------------
注意: 如果是采用變量賦值的方式聲明函數(shù)初茶,那么function本來就是表達(dá)式,所以可以直接加括號(hào)
const a = function() {
   console.log('11111111')
}();

eval命令

eval命令的作用是,將字符串當(dāng)作語句執(zhí)行

  • eval命令的作用是將字符串恼布,當(dāng)作語句執(zhí)行
eval('var a = 1;');
a // 1
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末螺戳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子折汞,更是在濱河造成了極大的恐慌倔幼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爽待,死亡現(xiàn)場(chǎng)離奇詭異损同,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸟款,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門膏燃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人何什,你說我怎么就攤上這事组哩。” “怎么了处渣?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵伶贰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我罐栈,道長(zhǎng)黍衙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任荠诬,我火速辦了婚禮琅翻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柑贞。我一直安慰自己望迎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布凌外。 她就那樣靜靜地躺著,像睡著了一般涛浙。 火紅的嫁衣襯著肌膚如雪康辑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天轿亮,我揣著相機(jī)與錄音疮薇,去河邊找鬼。 笑死我注,一個(gè)胖子當(dāng)著我的面吹牛按咒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播但骨,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼励七,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼智袭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掠抬,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤吼野,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后两波,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞳步,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年腰奋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了单起。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劣坊,死狀恐怖嘀倒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讼稚,我是刑警寧澤括儒,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站锐想,受9級(jí)特大地震影響帮寻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赠摇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一固逗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藕帜,春花似錦烫罩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至时甚,卻和暖如春隘弊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荒适。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工梨熙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刀诬。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓咽扇,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子质欲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 函數(shù)和對(duì)象 1树埠、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語言來說都是核心的概念。通過函數(shù)可以封裝任意多條語句把敞,而且...
    道無虛閱讀 4,563評(píng)論 0 5
  • ??面向?qū)ο螅∣bject-Oriented奋早,OO)的語言有一個(gè)標(biāo)志盛霎,那就是它們都有類的概念,而通過類可以創(chuàng)建任意...
    霜天曉閱讀 2,107評(píng)論 0 6
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡(jiǎn)單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,124評(píng)論 0 21
  • 文圖/ 資源整合(十六歲那年的詩) 既然鐘情于玫瑰 就勇敢地?fù)肀?即使弄得 滿身是刺 也不必后悔 因?yàn)?你畢...
    培紅說情感閱讀 160評(píng)論 0 0
  • 忽然間好想你耽装,人間天堂——美麗杭城愤炸;忽然間好想你,濃妝淡抹總相宜的西子湖:忽然間好想你掉奄,那些曾經(jīng)在杭城奮斗打拼的日...
    秦悠然閱讀 260評(píng)論 4 1