今天整理电脑,发现了很多早些年初学js时,一些比较困惑的程序题。然后摘抄出了其中的一些,有关原型、继承、作用域等相关的。供初学者学习,其中若有我理解错误的,欢迎大家批评指正。
下面不多说废话,直接上内容。
1、对象中属性或方法先从事例中寻找,若没有才去原型中寻找。
function A () {}
function B(a) {
this.a = a;
}
function C(a) {
if (a) {
this.a = a;
}
}
A.prototype.a = 1
B.prototype.a = 1;
C.prototype.a = 1;
console.log(new A().a); // 1
console.log(new B().a); // undefined
console.log(new C(2).a); // 2
2、原型链继承演示(简版)
function Fn() {
console.log(1);
}
var fn = new Fn();
console.log(fn); // FN
console.log(fn.__proto__ == Fn.prototype); // true
console.log(Fn.__proto__ == Function.prototype); // true
console.log(Function.prototype.__proto__ == Object.prototype); // true
console.log(Object.prototype.__proto__); // null
3、ES6继承
class Animal {
constructor(){
this.type = 'animal'
}
says(say){
console.log(this.type + ' says ' + say)
}
}
let animal = new Animal()
animal.says('hello') // animal says hello
console.log(animal.constructor); // FUN Animal
class Cat extends Animal {
constructor(){
super(); //修改this指向
this.type = 'cat'
}
}
let mini = new Cat();
console.log(mini.constructor == Cat); // true 实例的constructor指向构造函数
console.log(mini.type); // cat
console.log(mini.__proto__ == Cat.prototype); // true
console.log(Cat.prototype.__proto__ == Animal.prototype); // true
console.log(Animal.prototype.__proto__ == Object.prototype);// true
console.log(Object.prototype.__proto__); // true
4、作用域
1. 最近的作用域声明过,则去就近取
var tt = "a";
function test(){
//函数内部作用域声明过,所以会就近取。var 有声明提升。
//相当于在本作用域前声明
console.log(tt); // undefined
var tt = "b"
console.log(tt); // b
}
test();
function test2(){
//函数内部作用域没有声明过,
//直接从外部取值,调用。
console.log(tt); // a
}
test2();
2. 作用域发生变化
var length = "aaa" //若注释这句, window的length就为0
function fn(){
console.log(this.length);
}
var obj = {
length:"bbb",
test:function(fn){
fn(); // aaa this 为 window
console.log(this.length); ·// bbb this 为 obj
arguments[0](); // 1 this 为 arguments 对象 arguments的length为1
}
}
obj.test(fn);
3. this 指向
function fn(a,b){
alert(this+","+a);
}
fn.call("web",4,10) // web,4
var _name = "window name";
var hero = {
_name:"John Doe",
getName:function(){
return this._name;
}
}
var st=hero.getName;
console.log(st()); // window name 此处this为window
console.log(hero.getName()) // John Doe 此处this为hero对象
4. 原型,继承
function SuperType(){
this.car="宝马";
this.home="大别墅";
}
function SubType(){
}
SubType.prototype=new SuperType()
var pp=new SubType()
console.log(pp.car) // 宝马
5. 函数别名作用域
var func = function a (){
console.log(typeof a); // function
}
func();
console.log(typeof a) // undefined
// 在函数内部可以找到a,
// 但在外部a不存在,只有func;
6. 函数内修改值
var a = 1;
var obj = {b:2};
var fn = function(){};
fn.c = 3;
function test(x,y,z){
x = 4;
y.b = 5;
z.c = 6;
return z
}
test(a,obj,fn);
console.log(a+obj.b+fn.c); // 12 1, 5, 6
// 在函数内部,若直接修改参数的值,该值不会传递在外部,
// 但修改参数内部的某属性时,则可以改变
7. 作用域优先级问题
var a = 1;
function fn(a){
console.log(a);
var a = 3;
function a (){};
}
fn(2); // function
// 函数作用域同名变量,函数优先打印出来,其次是参数,再然后是局部变量,最后是全局变量。
// 那么意味着,暂且抛开全局变量不谈,局部变量 var 先声明提升,再然后是参数,最后是函数。
// 所以在程序开始运行的时候只能找到函数的值。
// 可能语言描述不清,看例子即可。
// 若注释 function a (){}; 打印值为 2
var a = 1;
function fn(a){
console.log(a);
var a = 3;
}
fn(2); // 2
// 若再去掉参数 打印值为 undefined 声明提升。
var a = 1;
function fn(){
console.log(a);
var a = 3;
}
fn();
// 若再去掉var a = 3; 打印值为 1
var a = 1;
function fn(){
console.log(a);
}
fn();
// 整体声明提升遵循这样一个规律, 局部变量 var > 参数 > 函数
好了,今天就暂时分享到这里。